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 * \file gl4cTextureViewTests.cpp
26 * \brief Implements conformance tests for "texture view" functionality.
27 */ /*-------------------------------------------------------------------*/
28
29 #include "gl4cTextureViewTests.hpp"
30 #include "deFloat16.h"
31 #include "deMath.h"
32 #include "gluContextInfo.hpp"
33 #include "glwFunctions.hpp"
34 #include "tcuFloat.hpp"
35 #include "tcuTestLog.hpp"
36 #include <algorithm>
37
38 /* Type definitions needed to handle GL_R11F_G11F_B10F internal format */
39 typedef tcu::Float<uint32_t, 5, 5, 15, 0> Float10;
40 typedef tcu::Float<uint32_t, 5, 6, 15, 0> Float11;
41
42 namespace gl4cts
43 {
44 using namespace TextureView;
45
46 /** Stores internalformat->view class associations */
47 const int internalformat_view_compatibility_array[] = {
48 /* [internalformat] [view class] */
49 GL_RGBA32F, VIEW_CLASS_128_BITS, GL_RGBA32UI, VIEW_CLASS_128_BITS, GL_RGBA32I, VIEW_CLASS_128_BITS, GL_RGB32F,
50 VIEW_CLASS_96_BITS, GL_RGB32UI, VIEW_CLASS_96_BITS, GL_RGB32I, VIEW_CLASS_96_BITS, GL_RGBA16F, VIEW_CLASS_64_BITS,
51 GL_RG32F, VIEW_CLASS_64_BITS, GL_RGBA16UI, VIEW_CLASS_64_BITS, GL_RG32UI, VIEW_CLASS_64_BITS, GL_RGBA16I,
52 VIEW_CLASS_64_BITS, GL_RG32I, VIEW_CLASS_64_BITS, GL_RGBA16, VIEW_CLASS_64_BITS, GL_RGBA16_SNORM,
53 VIEW_CLASS_64_BITS, GL_RGB16, VIEW_CLASS_48_BITS, GL_RGB16_SNORM, VIEW_CLASS_48_BITS, GL_RGB16F, VIEW_CLASS_48_BITS,
54 GL_RGB16UI, VIEW_CLASS_48_BITS, GL_RGB16I, VIEW_CLASS_48_BITS, GL_RG16F, VIEW_CLASS_32_BITS, GL_R11F_G11F_B10F,
55 VIEW_CLASS_32_BITS, GL_R32F, VIEW_CLASS_32_BITS, GL_RGB10_A2UI, VIEW_CLASS_32_BITS, GL_RGBA8UI, VIEW_CLASS_32_BITS,
56 GL_RG16UI, VIEW_CLASS_32_BITS, GL_R32UI, VIEW_CLASS_32_BITS, GL_RGBA8I, VIEW_CLASS_32_BITS, GL_RG16I,
57 VIEW_CLASS_32_BITS, GL_R32I, VIEW_CLASS_32_BITS, GL_RGB10_A2, VIEW_CLASS_32_BITS, GL_RGBA8, VIEW_CLASS_32_BITS,
58 GL_RG16, VIEW_CLASS_32_BITS, GL_RGBA8_SNORM, VIEW_CLASS_32_BITS, GL_RG16_SNORM, VIEW_CLASS_32_BITS, GL_SRGB8_ALPHA8,
59 VIEW_CLASS_32_BITS, GL_RGB9_E5, VIEW_CLASS_32_BITS, GL_RGB8, VIEW_CLASS_24_BITS, GL_RGB8_SNORM, VIEW_CLASS_24_BITS,
60 GL_SRGB8, VIEW_CLASS_24_BITS, GL_RGB8UI, VIEW_CLASS_24_BITS, GL_RGB8I, VIEW_CLASS_24_BITS, GL_R16F,
61 VIEW_CLASS_16_BITS, GL_RG8UI, VIEW_CLASS_16_BITS, GL_R16UI, VIEW_CLASS_16_BITS, GL_RG8I, VIEW_CLASS_16_BITS,
62 GL_R16I, VIEW_CLASS_16_BITS, GL_RG8, VIEW_CLASS_16_BITS, GL_R16, VIEW_CLASS_16_BITS, GL_RG8_SNORM,
63 VIEW_CLASS_16_BITS, GL_R16_SNORM, VIEW_CLASS_16_BITS, GL_R8UI, VIEW_CLASS_8_BITS, GL_R8I, VIEW_CLASS_8_BITS, GL_R8,
64 VIEW_CLASS_8_BITS, GL_R8_SNORM, VIEW_CLASS_8_BITS,
65
66 /* Compressed texture formats. */
67 GL_COMPRESSED_RED_RGTC1, VIEW_CLASS_RGTC1_RED, GL_COMPRESSED_SIGNED_RED_RGTC1, VIEW_CLASS_RGTC1_RED,
68 GL_COMPRESSED_RG_RGTC2, VIEW_CLASS_RGTC2_RG, GL_COMPRESSED_SIGNED_RG_RGTC2, VIEW_CLASS_RGTC2_RG,
69 GL_COMPRESSED_RGBA_BPTC_UNORM, VIEW_CLASS_BPTC_UNORM, GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM, VIEW_CLASS_BPTC_UNORM,
70 GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT, VIEW_CLASS_BPTC_FLOAT, GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT,
71 VIEW_CLASS_BPTC_FLOAT};
72
73 const int n_internalformat_view_compatibility_array_entries =
74 sizeof(internalformat_view_compatibility_array) / sizeof(internalformat_view_compatibility_array[0]);
75
76 /** Stores all internalformats valid in OpenGL 4.x. Information whether particular internalformat
77 * can be considered supported can be retrieved by calling TextureViewTests::isInternalformatSupported()
78 * function.
79 */
80 const glw::GLenum valid_gl_internalformats[] = {
81 /* Section 8.5.1 */
82 GL_RGBA32F, /* >= GL 4.0 */
83 GL_RGBA32I, /* >= GL 4.0 */
84 GL_RGBA32UI, /* >= GL 4.0 */
85 GL_RGBA16, /* >= GL 4.0 */
86 GL_RGBA16F, /* >= GL 4.0 */
87 GL_RGBA16I, /* >= GL 4.0 */
88 GL_RGBA16UI, /* >= GL 4.0 */
89 GL_RGBA8, /* >= GL 4.0 */
90 GL_RGBA8I, /* >= GL 4.0 */
91 GL_RGBA8UI, /* >= GL 4.0 */
92 GL_SRGB8_ALPHA8, /* >= GL 4.0 */
93 GL_RGB10_A2, /* >= GL 4.0 */
94 GL_RGB10_A2UI, /* >= GL 4.0 */
95 GL_RGB5_A1, /* >= GL 4.0 */
96 GL_RGBA4, /* >= GL 4.0 */
97 GL_R11F_G11F_B10F, /* >= GL 4.0 */
98 GL_RGB565, /* >= GL 4.2 */
99 GL_RG32F, /* >= GL 4.0 */
100 GL_RG32I, /* >= GL 4.0 */
101 GL_RG32UI, /* >= GL 4.0 */
102 GL_RG16, /* >= GL 4.0 */
103 GL_RG16F, /* >= GL 4.0 */
104 GL_RG16I, /* >= GL 4.0 */
105 GL_RG16UI, /* >= GL 4.0 */
106 GL_RG8, /* >= GL 4.0 */
107 GL_RG8I, /* >= GL 4.0 */
108 GL_RG8UI, /* >= GL 4.0 */
109 GL_R32F, /* >= GL 4.0 */
110 GL_R32I, /* >= GL 4.0 */
111 GL_R32UI, /* >= GL 4.0 */
112 GL_R16F, /* >= GL 4.0 */
113 GL_R16I, /* >= GL 4.0 */
114 GL_R16UI, /* >= GL 4.0 */
115 GL_R16, /* >= GL 4.0 */
116 GL_R8, /* >= GL 4.0 */
117 GL_R8I, /* >= GL 4.0 */
118 GL_R8UI, /* >= GL 4.0 */
119 GL_RGBA16_SNORM, /* >= GL 4.0 */
120 GL_RGBA8_SNORM, /* >= GL 4.0 */
121 GL_RGB32F, /* >= GL 4.0 */
122 GL_RGB32I, /* >= GL 4.0 */
123 GL_RGB32UI, /* >= GL 4.0 */
124 GL_RGB16_SNORM, /* >= GL 4.0 */
125 GL_RGB16F, /* >= GL 4.0 */
126 GL_RGB16I, /* >= GL 4.0 */
127 GL_RGB16UI, /* >= GL 4.0 */
128 GL_RGB16, /* >= GL 4.0 */
129 GL_RGB8_SNORM, /* >= GL 4.0 */
130 GL_RGB8, /* >= GL 4.0 */
131 GL_RGB8I, /* >= GL 4.0 */
132 GL_RGB8UI, /* >= GL 4.0 */
133 GL_SRGB8, /* >= GL 4.0 */
134 GL_RGB9_E5, /* >= GL 4.0 */
135 GL_RG16_SNORM, /* >= GL 4.0 */
136 GL_RG8_SNORM, /* >= GL 4.0 */
137 GL_R16_SNORM, /* >= GL 4.0 */
138 GL_R8_SNORM, /* >= GL 4.0 */
139
140 GL_DEPTH_COMPONENT32F, /* >= GL 4.0 */
141 GL_DEPTH_COMPONENT24, /* >= GL 4.0 */
142 GL_DEPTH_COMPONENT16, /* >= GL 4.0 */
143
144 GL_DEPTH32F_STENCIL8, /* >= GL 4.0 */
145 GL_DEPTH24_STENCIL8, /* >= GL 4.0 */
146
147 /* Table 8.14: generic compressed internalformats have been removed */
148 GL_COMPRESSED_RED_RGTC1, /* >= GL 4.0 */
149 GL_COMPRESSED_SIGNED_RED_RGTC1, /* >= GL 4.0 */
150 GL_COMPRESSED_RG_RGTC2, /* >= GL 4.0 */
151 GL_COMPRESSED_SIGNED_RG_RGTC2, /* >= GL 4.0 */
152 GL_COMPRESSED_RGBA_BPTC_UNORM, /* >= GL 4.2 */
153 GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM, /* >= GL 4.2 */
154 GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT, /* >= GL 4.2 */
155 GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT, /* >= GL 4.2 */
156 GL_COMPRESSED_RGB8_ETC2, /* >= GL 4.3 */
157 GL_COMPRESSED_SRGB8_ETC2, /* >= GL 4.3 */
158 GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, /* >= GL 4.3 */
159 GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, /* >= GL 4.3 */
160 GL_COMPRESSED_RGBA8_ETC2_EAC, /* >= GL 4.3 */
161 GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, /* >= GL 4.3 */
162 GL_COMPRESSED_R11_EAC, /* >= GL 4.3 */
163 GL_COMPRESSED_SIGNED_R11_EAC, /* >= GL 4.3 */
164 GL_COMPRESSED_RG11_EAC, /* >= GL 4.3 */
165 GL_COMPRESSED_SIGNED_RG11_EAC, /* >= GL 4.3 */
166 };
167
168 const int n_valid_gl_internalformats = sizeof(valid_gl_internalformats) / sizeof(valid_gl_internalformats[0]);
169
170 /** An array of texture targets that is used by a number of TextureViewUtilities methods. */
171 static glw::GLenum valid_texture_targets[] = {GL_TEXTURE_1D,
172 GL_TEXTURE_1D_ARRAY,
173 GL_TEXTURE_2D,
174 GL_TEXTURE_2D_ARRAY,
175 GL_TEXTURE_2D_MULTISAMPLE,
176 GL_TEXTURE_2D_MULTISAMPLE_ARRAY,
177 GL_TEXTURE_3D,
178 GL_TEXTURE_BUFFER,
179 GL_TEXTURE_CUBE_MAP,
180 GL_TEXTURE_CUBE_MAP_ARRAY,
181 GL_TEXTURE_RECTANGLE};
182 const unsigned int n_valid_texture_targets = sizeof(valid_texture_targets) / sizeof(valid_texture_targets[0]);
183
184 /** Retrieves amount of components defined by user-specified internalformat.
185 *
186 * This function throws TestError exception if @param internalformat is not recognized.
187 *
188 * @param internalformat Internalformat to use for the query.
189 *
190 * @return Requested value.
191 **/
getAmountOfComponentsForInternalformat(const glw::GLenum internalformat)192 unsigned int TextureViewUtilities::getAmountOfComponentsForInternalformat(const glw::GLenum internalformat)
193 {
194 unsigned int result = 0;
195
196 switch (internalformat)
197 {
198 case GL_COMPRESSED_RGBA_BPTC_UNORM:
199 case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
200 case GL_RGB10_A2:
201 case GL_RGB10_A2UI:
202 case GL_RGB5_A1:
203 case GL_RGBA16F:
204 case GL_RGBA16I:
205 case GL_RGBA16UI:
206 case GL_RGBA16:
207 case GL_RGBA16_SNORM:
208 case GL_RGBA32F:
209 case GL_RGBA32I:
210 case GL_RGBA32UI:
211 case GL_RGBA4:
212 case GL_RGBA8I:
213 case GL_RGBA8UI:
214 case GL_RGBA8:
215 case GL_RGBA8_SNORM:
216 case GL_SRGB8_ALPHA8:
217 {
218 result = 4;
219
220 break;
221 }
222
223 case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
224 case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
225 case GL_R11F_G11F_B10F:
226 case GL_RGB16_SNORM:
227 case GL_RGB16F:
228 case GL_RGB16I:
229 case GL_RGB16UI:
230 case GL_RGB16:
231 case GL_RGB32F:
232 case GL_RGB32I:
233 case GL_RGB32UI:
234 case GL_RGB565:
235 case GL_RGB8:
236 case GL_RGB8_SNORM:
237 case GL_RGB8I:
238 case GL_RGB8UI:
239 case GL_RGB9_E5:
240 case GL_SRGB8:
241 {
242 result = 3;
243
244 break;
245 }
246
247 case GL_COMPRESSED_RG_RGTC2:
248 case GL_COMPRESSED_SIGNED_RG_RGTC2:
249 case GL_RG16:
250 case GL_RG16F:
251 case GL_RG16I:
252 case GL_RG16UI:
253 case GL_RG16_SNORM:
254 case GL_RG32F:
255 case GL_RG32I:
256 case GL_RG32UI:
257 case GL_RG8:
258 case GL_RG8_SNORM:
259 case GL_RG8I:
260 case GL_RG8UI:
261 {
262 result = 2;
263
264 break;
265 }
266
267 case GL_COMPRESSED_RED_RGTC1:
268 case GL_COMPRESSED_SIGNED_RED_RGTC1:
269 case GL_DEPTH_COMPONENT16:
270 case GL_DEPTH_COMPONENT24:
271 case GL_DEPTH32F_STENCIL8: /* only one piece of information can be retrieved at a time */
272 case GL_DEPTH24_STENCIL8: /* only one piece of information can be retrieved at a time */
273 case GL_R16:
274 case GL_R16_SNORM:
275 case GL_R16F:
276 case GL_R16I:
277 case GL_R16UI:
278 case GL_R32F:
279 case GL_R32I:
280 case GL_R32UI:
281 case GL_R8_SNORM:
282 case GL_R8:
283 case GL_R8I:
284 case GL_R8UI:
285 {
286 result = 1;
287
288 break;
289 }
290
291 default:
292 {
293 TCU_FAIL("Unrecognized internalformat");
294 }
295 } /* switch (interalformat) */
296
297 return result;
298 }
299
300 /** Retrieves block size used by user-specified compressed internalformat.
301 *
302 * Throws TestError exception if @param internalformat is not recognized.
303 *
304 * @param internalformat Compressed internalformat to use for the query.
305 *
306 * @return Requested information (in bytes).
307 **/
getBlockSizeForCompressedInternalformat(const glw::GLenum internalformat)308 unsigned int TextureViewUtilities::getBlockSizeForCompressedInternalformat(const glw::GLenum internalformat)
309 {
310 unsigned int result = 0;
311
312 switch (internalformat)
313 {
314 case GL_COMPRESSED_RED_RGTC1:
315 case GL_COMPRESSED_SIGNED_RED_RGTC1:
316 {
317 result = 8;
318
319 break;
320 }
321
322 case GL_COMPRESSED_RG_RGTC2:
323 case GL_COMPRESSED_SIGNED_RG_RGTC2:
324 case GL_COMPRESSED_RGBA_BPTC_UNORM:
325 case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
326 case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
327 case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
328 {
329 result = 16;
330
331 break;
332 }
333
334 default:
335 {
336 TCU_FAIL("Unrecognized internalformat");
337 }
338 } /* switch (internalformat) */
339
340 return result;
341 }
342
343 /** Retrieves amount of bits used for R/G/B/A components by user-specified
344 * *non-compressed* internalformat.
345 *
346 * Throws TestError exception if @param internalformat is not recognized.
347 *
348 * @param internalformat Internalformat to use for the query. Must not describe
349 * compressed internalformat.
350 * @param out_rgba_size Must be spacious enough to hold 4 ints. Deref will be
351 * used to store requested information for R/G/B/A channels.
352 * Must not be NULL.
353 **/
getComponentSizeForInternalformat(const glw::GLenum internalformat,unsigned int * out_rgba_size)354 void TextureViewUtilities::getComponentSizeForInternalformat(const glw::GLenum internalformat,
355 unsigned int *out_rgba_size)
356 {
357 /* Note: Compressed textures are not supported by this function */
358
359 /* Reset all the values before we continue. */
360 memset(out_rgba_size, 0, 4 /* rgba */ * sizeof(unsigned int));
361
362 /* Depending on the user-specified internalformat, update relevant arguments */
363 switch (internalformat)
364 {
365 case GL_RGBA32F:
366 case GL_RGBA32I:
367 case GL_RGBA32UI:
368 {
369 out_rgba_size[0] = 32;
370 out_rgba_size[1] = 32;
371 out_rgba_size[2] = 32;
372 out_rgba_size[3] = 32;
373
374 break;
375 }
376
377 case GL_RGBA16F:
378 case GL_RGBA16I:
379 case GL_RGBA16UI:
380 case GL_RGBA16:
381 case GL_RGBA16_SNORM:
382 {
383 out_rgba_size[0] = 16;
384 out_rgba_size[1] = 16;
385 out_rgba_size[2] = 16;
386 out_rgba_size[3] = 16;
387
388 break;
389 }
390
391 case GL_RGBA8I:
392 case GL_RGBA8UI:
393 case GL_RGBA8:
394 case GL_RGBA8_SNORM:
395 case GL_SRGB8_ALPHA8:
396 {
397 out_rgba_size[0] = 8;
398 out_rgba_size[1] = 8;
399 out_rgba_size[2] = 8;
400 out_rgba_size[3] = 8;
401
402 break;
403 }
404
405 case GL_RGB10_A2:
406 case GL_RGB10_A2UI:
407 {
408 out_rgba_size[0] = 10;
409 out_rgba_size[1] = 10;
410 out_rgba_size[2] = 10;
411 out_rgba_size[3] = 2;
412
413 break;
414 }
415
416 case GL_RGB5_A1:
417 {
418 out_rgba_size[0] = 5;
419 out_rgba_size[1] = 5;
420 out_rgba_size[2] = 5;
421 out_rgba_size[3] = 1;
422
423 break;
424 }
425
426 case GL_RGBA4:
427 {
428 out_rgba_size[0] = 4;
429 out_rgba_size[1] = 4;
430 out_rgba_size[2] = 4;
431 out_rgba_size[3] = 4;
432
433 break;
434 }
435
436 case GL_RGB9_E5:
437 {
438 out_rgba_size[0] = 9;
439 out_rgba_size[1] = 9;
440 out_rgba_size[2] = 9;
441 out_rgba_size[3] = 5;
442
443 break;
444 }
445
446 case GL_R11F_G11F_B10F:
447 {
448 out_rgba_size[0] = 11;
449 out_rgba_size[1] = 11;
450 out_rgba_size[2] = 10;
451
452 break;
453 }
454
455 case GL_RGB565:
456 {
457 out_rgba_size[0] = 5;
458 out_rgba_size[1] = 6;
459 out_rgba_size[2] = 5;
460
461 break;
462 }
463
464 case GL_RGB32F:
465 case GL_RGB32I:
466 case GL_RGB32UI:
467 {
468 out_rgba_size[0] = 32;
469 out_rgba_size[1] = 32;
470 out_rgba_size[2] = 32;
471
472 break;
473 }
474
475 case GL_RGB16_SNORM:
476 case GL_RGB16F:
477 case GL_RGB16I:
478 case GL_RGB16UI:
479 case GL_RGB16:
480 {
481 out_rgba_size[0] = 16;
482 out_rgba_size[1] = 16;
483 out_rgba_size[2] = 16;
484
485 break;
486 }
487
488 case GL_RGB8_SNORM:
489 case GL_RGB8:
490 case GL_RGB8I:
491 case GL_RGB8UI:
492 case GL_SRGB8:
493 {
494 out_rgba_size[0] = 8;
495 out_rgba_size[1] = 8;
496 out_rgba_size[2] = 8;
497
498 break;
499 }
500
501 case GL_RG32F:
502 case GL_RG32I:
503 case GL_RG32UI:
504 {
505 out_rgba_size[0] = 32;
506 out_rgba_size[1] = 32;
507
508 break;
509 }
510
511 case GL_RG16:
512 case GL_RG16F:
513 case GL_RG16I:
514 case GL_RG16UI:
515 case GL_RG16_SNORM:
516 {
517 out_rgba_size[0] = 16;
518 out_rgba_size[1] = 16;
519
520 break;
521 }
522
523 case GL_RG8:
524 case GL_RG8I:
525 case GL_RG8UI:
526 case GL_RG8_SNORM:
527 {
528 out_rgba_size[0] = 8;
529 out_rgba_size[1] = 8;
530
531 break;
532 }
533
534 case GL_R32F:
535 case GL_R32I:
536 case GL_R32UI:
537 {
538 out_rgba_size[0] = 32;
539
540 break;
541 }
542
543 case GL_R16F:
544 case GL_R16I:
545 case GL_R16UI:
546 case GL_R16:
547 case GL_R16_SNORM:
548 case GL_DEPTH_COMPONENT16:
549 {
550 out_rgba_size[0] = 16;
551
552 break;
553 }
554
555 case GL_R8:
556 case GL_R8I:
557 case GL_R8UI:
558 case GL_R8_SNORM:
559 {
560 out_rgba_size[0] = 8;
561
562 break;
563 }
564
565 case GL_DEPTH_COMPONENT24:
566 {
567 out_rgba_size[0] = 24;
568
569 break;
570 }
571
572 case GL_DEPTH32F_STENCIL8:
573 {
574 out_rgba_size[0] = 32;
575 out_rgba_size[1] = 8;
576
577 break;
578 }
579
580 case GL_DEPTH24_STENCIL8:
581 {
582 out_rgba_size[0] = 24;
583 out_rgba_size[1] = 8;
584
585 break;
586 }
587
588 default:
589 {
590 TCU_FAIL("Unrecognized internalformat");
591 }
592 } /* switch (interalformat) */
593 }
594
595 /** Tells how many bits per components should be used to define input data with
596 * user-specified type.
597 *
598 * Throws TestError exception if @param type is not recognized.
599 *
600 * @param type Type to use for the query.
601 * @param out_rgba_size Deref will be used to store requested information. Must
602 * not be NULL. Must be capacious enough to hold 4 ints.
603 *
604 **/
getComponentSizeForType(const glw::GLenum type,unsigned int * out_rgba_size)605 void TextureViewUtilities::getComponentSizeForType(const glw::GLenum type, unsigned int *out_rgba_size)
606 {
607 memset(out_rgba_size, 0, sizeof(unsigned int) * 4 /* rgba */);
608
609 switch (type)
610 {
611 case GL_BYTE:
612 case GL_UNSIGNED_BYTE:
613 {
614 out_rgba_size[0] = 8;
615 out_rgba_size[1] = 8;
616 out_rgba_size[2] = 8;
617 out_rgba_size[3] = 8;
618
619 break;
620 }
621
622 case GL_FLOAT:
623 case GL_UNSIGNED_INT:
624 case GL_INT:
625 {
626 out_rgba_size[0] = 32;
627 out_rgba_size[1] = 32;
628 out_rgba_size[2] = 32;
629 out_rgba_size[3] = 32;
630
631 break;
632 }
633
634 case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
635 {
636 out_rgba_size[0] = 8;
637 out_rgba_size[1] = 24;
638 out_rgba_size[2] = 32;
639 out_rgba_size[3] = 0;
640
641 break;
642 }
643
644 case GL_HALF_FLOAT:
645 case GL_UNSIGNED_SHORT:
646 case GL_SHORT:
647 {
648 out_rgba_size[0] = 16;
649 out_rgba_size[1] = 16;
650 out_rgba_size[2] = 16;
651 out_rgba_size[3] = 16;
652
653 break;
654 }
655
656 case GL_UNSIGNED_INT_10_10_10_2:
657 {
658 out_rgba_size[0] = 10;
659 out_rgba_size[1] = 10;
660 out_rgba_size[2] = 10;
661 out_rgba_size[3] = 2;
662
663 break;
664 }
665
666 case GL_UNSIGNED_INT_10F_11F_11F_REV:
667 {
668 out_rgba_size[0] = 11;
669 out_rgba_size[1] = 11;
670 out_rgba_size[2] = 10;
671
672 break;
673 }
674
675 case GL_UNSIGNED_INT_24_8:
676 {
677 out_rgba_size[0] = 24;
678 out_rgba_size[1] = 8;
679 out_rgba_size[2] = 0;
680 out_rgba_size[3] = 0;
681
682 break;
683 }
684
685 case GL_UNSIGNED_INT_2_10_10_10_REV:
686 {
687 out_rgba_size[0] = 10;
688 out_rgba_size[1] = 10;
689 out_rgba_size[2] = 10;
690 out_rgba_size[3] = 2;
691
692 break;
693 }
694
695 case GL_UNSIGNED_INT_5_9_9_9_REV:
696 {
697 out_rgba_size[0] = 9;
698 out_rgba_size[1] = 9;
699 out_rgba_size[2] = 9;
700 out_rgba_size[3] = 5;
701
702 break;
703 }
704
705 default:
706 {
707 TCU_FAIL("Unrecognized type");
708 }
709 } /* switch (type) */
710 }
711
712 /** Returns strings naming GL error codes.
713 *
714 * @param error_code GL error code.
715 *
716 * @return Requested strings or "[?]" if @param error_code was not
717 * recognized.
718 **/
getErrorCodeString(const glw::GLint error_code)719 const char *TextureViewUtilities::getErrorCodeString(const glw::GLint error_code)
720 {
721 switch (error_code)
722 {
723 case GL_INVALID_ENUM:
724 return "GL_INVALID_ENUM";
725 case GL_INVALID_FRAMEBUFFER_OPERATION:
726 return "GL_INVALID_FRAMEBUFFER_OPERATION";
727 case GL_INVALID_OPERATION:
728 return "GL_INVALID_OPERATION";
729 case GL_INVALID_VALUE:
730 return "GL_INVALID_VALUE";
731 case GL_NO_ERROR:
732 return "GL_NO_ERROR";
733 case GL_OUT_OF_MEMORY:
734 return "GL_OUT_OF_MEMORY";
735 case GL_STACK_OVERFLOW:
736 return "GL_STACK_OVERFLOW";
737 case GL_STACK_UNDERFLOW:
738 return "GL_STACK_UNDERFLOW";
739 default:
740 return "[?]";
741 }
742 }
743
744 /** Tells what the format of user-specified internalformat is (eg. whether it's a FP,
745 * unorm, snorm, etc.). Note: this is NOT the GL-speak format.
746 *
747 * Supports both compressed and non-compressed internalformats.
748 * Throws TestError exception if @param internalformat is not recognized.
749 *
750 * @param internalformat Internalformat to use for the query.
751 *
752 * @return Requested information.
753 *
754 **/
getFormatOfInternalformat(const glw::GLenum internalformat)755 _format TextureViewUtilities::getFormatOfInternalformat(const glw::GLenum internalformat)
756 {
757 _format result = FORMAT_UNDEFINED;
758
759 switch (internalformat)
760 {
761 case GL_COMPRESSED_RG_RGTC2:
762 case GL_COMPRESSED_RGBA_BPTC_UNORM:
763 case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
764 case GL_COMPRESSED_RED_RGTC1:
765 case GL_RGBA16:
766 case GL_RGBA4:
767 case GL_RGBA8:
768 case GL_RGB10_A2:
769 case GL_RGB16:
770 case GL_RGB5_A1:
771 case GL_RGB565:
772 case GL_RGB8:
773 case GL_RG16:
774 case GL_RG8:
775 case GL_R16:
776 case GL_R8:
777 case GL_SRGB8:
778 case GL_SRGB8_ALPHA8:
779 {
780 result = FORMAT_UNORM;
781
782 break;
783 }
784
785 case GL_COMPRESSED_SIGNED_RED_RGTC1:
786 case GL_COMPRESSED_SIGNED_RG_RGTC2:
787 case GL_RGBA16_SNORM:
788 case GL_RGBA8_SNORM:
789 case GL_RGB16_SNORM:
790 case GL_RGB8_SNORM:
791 case GL_RG16_SNORM:
792 case GL_RG8_SNORM:
793 case GL_R16_SNORM:
794 case GL_R8_SNORM:
795 {
796 result = FORMAT_SNORM;
797
798 break;
799 }
800
801 case GL_RGB10_A2UI:
802 case GL_RGBA16UI:
803 case GL_RGBA32UI:
804 case GL_RGBA8UI:
805 case GL_RGB16UI:
806 case GL_RGB32UI:
807 case GL_RGB8UI:
808 case GL_RG16UI:
809 case GL_RG32UI:
810 case GL_RG8UI:
811 case GL_R16UI:
812 case GL_R32UI:
813 case GL_R8UI:
814 {
815 result = FORMAT_UNSIGNED_INTEGER;
816
817 break;
818 }
819
820 case GL_RGB9_E5:
821 {
822 result = FORMAT_RGBE;
823
824 break;
825 }
826
827 case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
828 case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
829 case GL_DEPTH_COMPONENT16:
830 case GL_DEPTH_COMPONENT24:
831 case GL_DEPTH_COMPONENT32F:
832 case GL_R11F_G11F_B10F:
833 case GL_RGBA16F:
834 case GL_RGBA32F:
835 case GL_RGB16F:
836 case GL_RGB32F:
837 case GL_RG16F:
838 case GL_RG32F:
839 case GL_R16F:
840 case GL_R32F:
841 {
842 result = FORMAT_FLOAT;
843
844 break;
845 }
846
847 case GL_RGBA16I:
848 case GL_RGBA32I:
849 case GL_RGBA8I:
850 case GL_RGB16I:
851 case GL_RGB32I:
852 case GL_RGB8I:
853 case GL_RG16I:
854 case GL_RG32I:
855 case GL_RG8I:
856 case GL_R16I:
857 case GL_R32I:
858 case GL_R8I:
859 {
860 result = FORMAT_SIGNED_INTEGER;
861
862 break;
863 }
864
865 default:
866 {
867 TCU_FAIL("Unrecognized internalformat");
868 }
869 } /* switch (interalformat) */
870
871 return result;
872 }
873
874 /** Returns GL format that is compatible with user-specified internalformat.
875 *
876 * Throws TestError exception if @param internalformat is not recognized.
877 *
878 * @param internalformat Internalformat to use for the query.
879 *
880 * @return Requested information.
881 **/
getGLFormatOfInternalformat(const glw::GLenum internalformat)882 glw::GLenum TextureViewUtilities::getGLFormatOfInternalformat(const glw::GLenum internalformat)
883 {
884 glw::GLenum result = FORMAT_UNDEFINED;
885
886 switch (internalformat)
887 {
888 case GL_COMPRESSED_RGBA_BPTC_UNORM:
889 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
890 case GL_COMPRESSED_RGBA8_ETC2_EAC:
891 case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
892 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
893 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
894 {
895 result = GL_COMPRESSED_RGBA;
896
897 break;
898 }
899
900 case GL_RGB10_A2:
901 case GL_RGB5_A1:
902 case GL_RGBA16:
903 case GL_RGBA16F:
904 case GL_RGBA16_SNORM:
905 case GL_RGBA32F:
906 case GL_RGBA4:
907 case GL_RGBA8:
908 case GL_RGBA8_SNORM:
909 case GL_SRGB8_ALPHA8:
910 {
911 result = GL_RGBA;
912
913 break;
914 }
915
916 case GL_RGB10_A2UI:
917 case GL_RGBA16I:
918 case GL_RGBA16UI:
919 case GL_RGBA32I:
920 case GL_RGBA32UI:
921 case GL_RGBA8I:
922 case GL_RGBA8UI:
923 {
924 result = GL_RGBA_INTEGER;
925
926 break;
927 }
928
929 case GL_COMPRESSED_RGB8_ETC2:
930 case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
931 case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
932 case GL_COMPRESSED_SRGB8_ETC2:
933 {
934 result = GL_COMPRESSED_RGB;
935
936 break;
937 }
938
939 case GL_R11F_G11F_B10F:
940 case GL_RGB16:
941 case GL_RGB16_SNORM:
942 case GL_RGB16F:
943 case GL_RGB32F:
944 case GL_RGB565:
945 case GL_RGB8:
946 case GL_RGB8_SNORM:
947 case GL_RGB9_E5:
948 case GL_SRGB8:
949 {
950 result = GL_RGB;
951
952 break;
953 }
954
955 case GL_RGB16I:
956 case GL_RGB16UI:
957 case GL_RGB32I:
958 case GL_RGB32UI:
959 case GL_RGB8I:
960 case GL_RGB8UI:
961 {
962 result = GL_RGB_INTEGER;
963
964 break;
965 }
966
967 case GL_COMPRESSED_RG_RGTC2:
968 case GL_COMPRESSED_RG11_EAC:
969 case GL_COMPRESSED_SIGNED_RG_RGTC2:
970 case GL_COMPRESSED_SIGNED_RG11_EAC:
971 {
972 result = GL_COMPRESSED_RG;
973
974 break;
975 }
976
977 case GL_RG16:
978 case GL_RG16_SNORM:
979 case GL_RG16F:
980 case GL_RG32F:
981 case GL_RG8:
982 case GL_RG8_SNORM:
983 {
984 result = GL_RG;
985
986 break;
987 }
988
989 case GL_RG16I:
990 case GL_RG16UI:
991 case GL_RG32I:
992 case GL_RG32UI:
993 case GL_RG8I:
994 case GL_RG8UI:
995 {
996 result = GL_RG_INTEGER;
997
998 break;
999 }
1000
1001 case GL_COMPRESSED_R11_EAC:
1002 case GL_COMPRESSED_RED_RGTC1:
1003 case GL_COMPRESSED_SIGNED_R11_EAC:
1004 case GL_COMPRESSED_SIGNED_RED_RGTC1:
1005 {
1006 result = GL_COMPRESSED_RED;
1007
1008 break;
1009 }
1010
1011 case GL_R16:
1012 case GL_R16F:
1013 case GL_R16_SNORM:
1014 case GL_R32F:
1015 case GL_R8:
1016 case GL_R8_SNORM:
1017 {
1018 result = GL_RED;
1019
1020 break;
1021 }
1022
1023 case GL_R16I:
1024 case GL_R16UI:
1025 case GL_R32I:
1026 case GL_R32UI:
1027 case GL_R8I:
1028 case GL_R8UI:
1029 {
1030 result = GL_RED_INTEGER;
1031
1032 break;
1033 }
1034
1035 case GL_DEPTH_COMPONENT16:
1036 case GL_DEPTH_COMPONENT24:
1037 case GL_DEPTH_COMPONENT32F:
1038 {
1039 result = GL_DEPTH_COMPONENT;
1040
1041 break;
1042 }
1043
1044 case GL_DEPTH24_STENCIL8:
1045 case GL_DEPTH32F_STENCIL8:
1046 {
1047 result = GL_DEPTH_STENCIL;
1048
1049 break;
1050 }
1051
1052 default:
1053 {
1054 TCU_FAIL("Unrecognized internalformat");
1055 }
1056 } /* switch (internalformat) */
1057
1058 return result;
1059 }
1060
1061 /** Returns a string that corresponds to a GLSL type that can act as input to user-specified
1062 * sampler type, and which can hold user-specified amount of components.
1063 *
1064 * Throws TestError exception if either of the arguments was found invalid.
1065 *
1066 * @param sampler_type Type of the sampler to use for the query.
1067 * @param n_components Amount of components to use for the query.
1068 *
1069 * @return Requested string.
1070 **/
getGLSLDataTypeForSamplerType(const _sampler_type sampler_type,const unsigned int n_components)1071 const char *TextureViewUtilities::getGLSLDataTypeForSamplerType(const _sampler_type sampler_type,
1072 const unsigned int n_components)
1073 {
1074 const char *result = "";
1075
1076 switch (sampler_type)
1077 {
1078 case SAMPLER_TYPE_FLOAT:
1079 {
1080 switch (n_components)
1081 {
1082 case 1:
1083 result = "float";
1084 break;
1085 case 2:
1086 result = "vec2";
1087 break;
1088 case 3:
1089 result = "vec3";
1090 break;
1091 case 4:
1092 result = "vec4";
1093 break;
1094
1095 default:
1096 {
1097 TCU_FAIL("Unsupported number of components");
1098 }
1099 } /* switch (n_components) */
1100
1101 break;
1102 }
1103
1104 case SAMPLER_TYPE_SIGNED_INTEGER:
1105 {
1106 switch (n_components)
1107 {
1108 case 1:
1109 result = "int";
1110 break;
1111 case 2:
1112 result = "ivec2";
1113 break;
1114 case 3:
1115 result = "ivec3";
1116 break;
1117 case 4:
1118 result = "ivec4";
1119 break;
1120
1121 default:
1122 {
1123 TCU_FAIL("Unsupported number of components");
1124 }
1125 } /* switch (n_components) */
1126
1127 break;
1128 }
1129
1130 case SAMPLER_TYPE_UNSIGNED_INTEGER:
1131 {
1132 switch (n_components)
1133 {
1134 case 1:
1135 result = "uint";
1136 break;
1137 case 2:
1138 result = "uvec2";
1139 break;
1140 case 3:
1141 result = "uvec3";
1142 break;
1143 case 4:
1144 result = "uvec4";
1145 break;
1146
1147 default:
1148 {
1149 TCU_FAIL("Unsupported number of components");
1150 }
1151 } /* switch (n_components) */
1152
1153 break;
1154 }
1155
1156 default:
1157 {
1158 TCU_FAIL("Unrecognized sampler type");
1159 }
1160 } /* switch (sampler_type) */
1161
1162 return result;
1163 }
1164
1165 /** Retrieves a string defining a sampler type in GLSL which corresponds to user-specified internal
1166 * sampler type.
1167 *
1168 * Throws TestError exception if @param sampler_type was not recognized.
1169 *
1170 * @param sampler_type Internal sampler type to use for the query.
1171 *
1172 * @return Requested string.
1173 **/
getGLSLTypeForSamplerType(const _sampler_type sampler_type)1174 const char *TextureViewUtilities::getGLSLTypeForSamplerType(const _sampler_type sampler_type)
1175 {
1176 const char *result = "";
1177
1178 switch (sampler_type)
1179 {
1180 case SAMPLER_TYPE_FLOAT:
1181 result = "sampler2D";
1182 break;
1183 case SAMPLER_TYPE_SIGNED_INTEGER:
1184 result = "isampler2D";
1185 break;
1186 case SAMPLER_TYPE_UNSIGNED_INTEGER:
1187 result = "usampler2D";
1188 break;
1189
1190 default:
1191 {
1192 TCU_FAIL("Unrecognized sampler type");
1193 }
1194 } /* switch (sampler_type) */
1195
1196 return result;
1197 }
1198
1199 /** Returns a vector of texture+view internalformat combinations that are known to be incompatible.
1200 *
1201 * @return Requested information.
1202 **/
1203 TextureViewUtilities::_incompatible_internalformat_pairs TextureViewUtilities::
getIllegalTextureAndViewInternalformatCombinations()1204 getIllegalTextureAndViewInternalformatCombinations()
1205 {
1206 TextureViewUtilities::_incompatible_internalformat_pairs result;
1207
1208 /* Iterate in two loops over the set of supported internalformats */
1209 for (int n_texture_internalformat = 0;
1210 n_texture_internalformat <
1211 (n_internalformat_view_compatibility_array_entries / 2); /* the array stores two values per entry */
1212 ++n_texture_internalformat)
1213 {
1214 glw::GLenum src_internalformat = internalformat_view_compatibility_array[(n_texture_internalformat * 2) + 0];
1215 _view_class src_view_class =
1216 (_view_class)internalformat_view_compatibility_array[(n_texture_internalformat * 2) + 1];
1217
1218 for (int n_view_internalformat = n_texture_internalformat + 1;
1219 n_view_internalformat < (n_internalformat_view_compatibility_array_entries >> 1); ++n_view_internalformat)
1220 {
1221 glw::GLenum view_internalformat = internalformat_view_compatibility_array[(n_view_internalformat * 2) + 0];
1222 _view_class view_view_class =
1223 (_view_class)internalformat_view_compatibility_array[(n_view_internalformat * 2) + 1];
1224
1225 if (src_view_class != view_view_class)
1226 {
1227 result.push_back(_internalformat_pair(src_internalformat, view_internalformat));
1228 }
1229 } /* for (all internalformats we can use for the texture view) */
1230 } /* for (all internalformats we can use for the parent texture) */
1231
1232 return result;
1233 }
1234
1235 /** Returns a vector of texture+view target texture combinations that are known to be incompatible.
1236 *
1237 * @return Requested information.
1238 **/
1239 TextureViewUtilities::_incompatible_texture_target_pairs TextureViewUtilities::
getIllegalTextureAndViewTargetCombinations()1240 getIllegalTextureAndViewTargetCombinations()
1241 {
1242 _incompatible_texture_target_pairs result;
1243
1244 /* Iterate through all combinations of texture targets and store those that are
1245 * reported as invalid
1246 */
1247 for (unsigned int n_parent_texture_target = 0; n_parent_texture_target < n_valid_texture_targets;
1248 ++n_parent_texture_target)
1249 {
1250 glw::GLenum parent_texture_target = valid_texture_targets[n_parent_texture_target];
1251
1252 for (unsigned int n_view_texture_target = 0; n_view_texture_target < n_valid_texture_targets;
1253 ++n_view_texture_target)
1254 {
1255 glw::GLenum view_texture_target = valid_texture_targets[n_view_texture_target];
1256
1257 if (!isLegalTextureTargetForTextureView(parent_texture_target, view_texture_target))
1258 {
1259 result.push_back(_internalformat_pair(parent_texture_target, view_texture_target));
1260 }
1261 } /* for (all texture targets considered for views) */
1262 } /* for (all texture targets considered for parent texture) */
1263
1264 return result;
1265 }
1266
1267 /** Returns internalformats associated with user-specified view class.
1268 *
1269 * @param view_class View class to use for the query.
1270 *
1271 * @return Requested information.
1272 **/
getInternalformatsFromViewClass(_view_class view_class)1273 TextureViewUtilities::_internalformats TextureViewUtilities::getInternalformatsFromViewClass(_view_class view_class)
1274 {
1275 _internalformats result;
1276
1277 /* Iterate over the data array and push those internalformats that match the requested view class */
1278 const unsigned int n_array_elements = n_internalformat_view_compatibility_array_entries;
1279
1280 for (unsigned int n_array_pair = 0; n_array_pair < (n_array_elements >> 1); ++n_array_pair)
1281 {
1282 const glw::GLenum internalformat = internalformat_view_compatibility_array[n_array_pair * 2 + 0];
1283 const _view_class current_view_class =
1284 (_view_class)internalformat_view_compatibility_array[n_array_pair * 2 + 1];
1285
1286 if (current_view_class == view_class)
1287 {
1288 result.push_back(internalformat);
1289 }
1290 } /* for (all pairs in the data array) */
1291
1292 return result;
1293 }
1294
1295 /** Returns a string defining user-specified internalformat.
1296 *
1297 * Throws a TestError exception if @param internalformat was not recognized.
1298 *
1299 * @param internalformat Internalformat to use for the query.
1300 *
1301 * @return Requested string.
1302 **/
getInternalformatString(const glw::GLenum internalformat)1303 const char *TextureViewUtilities::getInternalformatString(const glw::GLenum internalformat)
1304 {
1305 const char *result = "[?]";
1306
1307 switch (internalformat)
1308 {
1309 case GL_RGBA32F:
1310 result = "GL_RGBA32F";
1311 break;
1312 case GL_RGBA32I:
1313 result = "GL_RGBA32I";
1314 break;
1315 case GL_RGBA32UI:
1316 result = "GL_RGBA32UI";
1317 break;
1318 case GL_RGBA16:
1319 result = "GL_RGBA16";
1320 break;
1321 case GL_RGBA16F:
1322 result = "GL_RGBA16F";
1323 break;
1324 case GL_RGBA16I:
1325 result = "GL_RGBA16I";
1326 break;
1327 case GL_RGBA16UI:
1328 result = "GL_RGBA16UI";
1329 break;
1330 case GL_RGBA8:
1331 result = "GL_RGBA8";
1332 break;
1333 case GL_RGBA8I:
1334 result = "GL_RGBA8I";
1335 break;
1336 case GL_RGBA8UI:
1337 result = "GL_RGBA8UI";
1338 break;
1339 case GL_SRGB8_ALPHA8:
1340 result = "GL_SRGB8_ALPHA8";
1341 break;
1342 case GL_RGB10_A2:
1343 result = "GL_RGB10_A2";
1344 break;
1345 case GL_RGB10_A2UI:
1346 result = "GL_RGB10_A2UI";
1347 break;
1348 case GL_RGB5_A1:
1349 result = "GL_RGB5_A1";
1350 break;
1351 case GL_RGBA4:
1352 result = "GL_RGBA4";
1353 break;
1354 case GL_R11F_G11F_B10F:
1355 result = "GL_R11F_G11F_B10F";
1356 break;
1357 case GL_RGB565:
1358 result = "GL_RGB565";
1359 break;
1360 case GL_RG32F:
1361 result = "GL_RG32F";
1362 break;
1363 case GL_RG32I:
1364 result = "GL_RG32I";
1365 break;
1366 case GL_RG32UI:
1367 result = "GL_RG32UI";
1368 break;
1369 case GL_RG16:
1370 result = "GL_RG16";
1371 break;
1372 case GL_RG16F:
1373 result = "GL_RG16F";
1374 break;
1375 case GL_RG16I:
1376 result = "GL_RG16I";
1377 break;
1378 case GL_RG16UI:
1379 result = "GL_RG16UI";
1380 break;
1381 case GL_RG8:
1382 result = "GL_RG8";
1383 break;
1384 case GL_RG8I:
1385 result = "GL_RG8I";
1386 break;
1387 case GL_RG8UI:
1388 result = "GL_RG8UI";
1389 break;
1390 case GL_R32F:
1391 result = "GL_R32F";
1392 break;
1393 case GL_R32I:
1394 result = "GL_R32I";
1395 break;
1396 case GL_R32UI:
1397 result = "GL_R32UI";
1398 break;
1399 case GL_R16F:
1400 result = "GL_R16F";
1401 break;
1402 case GL_R16I:
1403 result = "GL_R16I";
1404 break;
1405 case GL_R16UI:
1406 result = "GL_R16UI";
1407 break;
1408 case GL_R16:
1409 result = "GL_R16";
1410 break;
1411 case GL_R8:
1412 result = "GL_R8";
1413 break;
1414 case GL_R8I:
1415 result = "GL_R8I";
1416 break;
1417 case GL_R8UI:
1418 result = "GL_R8UI";
1419 break;
1420 case GL_RGBA16_SNORM:
1421 result = "GL_RGBA16_SNORM";
1422 break;
1423 case GL_RGBA8_SNORM:
1424 result = "GL_RGBA8_SNORM";
1425 break;
1426 case GL_RGB32F:
1427 result = "GL_RGB32F";
1428 break;
1429 case GL_RGB32I:
1430 result = "GL_RGB32I";
1431 break;
1432 case GL_RGB32UI:
1433 result = "GL_RGB32UI";
1434 break;
1435 case GL_RGB16_SNORM:
1436 result = "GL_RGB16_SNORM";
1437 break;
1438 case GL_RGB16F:
1439 result = "GL_RGB16F";
1440 break;
1441 case GL_RGB16I:
1442 result = "GL_RGB16I";
1443 break;
1444 case GL_RGB16UI:
1445 result = "GL_RGB16UI";
1446 break;
1447 case GL_RGB16:
1448 result = "GL_RGB16";
1449 break;
1450 case GL_RGB8_SNORM:
1451 result = "GL_RGB8_SNORM";
1452 break;
1453 case GL_RGB8:
1454 result = "GL_RGB8";
1455 break;
1456 case GL_RGB8I:
1457 result = "GL_RGB8I";
1458 break;
1459 case GL_RGB8UI:
1460 result = "GL_RGB8UI";
1461 break;
1462 case GL_SRGB8:
1463 result = "GL_SRGB8";
1464 break;
1465 case GL_RGB9_E5:
1466 result = "GL_RGB9_E5";
1467 break;
1468 case GL_RG16_SNORM:
1469 result = "GL_RG16_SNORM";
1470 break;
1471 case GL_RG8_SNORM:
1472 result = "GL_RG8_SNORM";
1473 break;
1474 case GL_R16_SNORM:
1475 result = "GL_R16_SNORM";
1476 break;
1477 case GL_R8_SNORM:
1478 result = "GL_R8_SNORM";
1479 break;
1480 case GL_DEPTH_COMPONENT32F:
1481 result = "GL_DEPTH_COMPONENT32F";
1482 break;
1483 case GL_DEPTH_COMPONENT24:
1484 result = "GL_DEPTH_COMPONENT24";
1485 break;
1486 case GL_DEPTH_COMPONENT16:
1487 result = "GL_DEPTH_COMPONENT16";
1488 break;
1489 case GL_DEPTH32F_STENCIL8:
1490 result = "GL_DEPTH32F_STENCIL8";
1491 break;
1492 case GL_DEPTH24_STENCIL8:
1493 result = "GL_DEPTH24_STENCIL8";
1494 break;
1495 case GL_COMPRESSED_RED_RGTC1:
1496 result = "GL_COMPRESSED_RED_RGTC1";
1497 break;
1498 case GL_COMPRESSED_SIGNED_RED_RGTC1:
1499 result = "GL_COMPRESSED_SIGNED_RED_RGTC1";
1500 break;
1501 case GL_COMPRESSED_RG_RGTC2:
1502 result = "GL_COMPRESSED_RG_RGTC2";
1503 break;
1504 case GL_COMPRESSED_SIGNED_RG_RGTC2:
1505 result = "GL_COMPRESSED_SIGNED_RG_RGTC2";
1506 break;
1507 case GL_COMPRESSED_RGBA_BPTC_UNORM:
1508 result = "GL_COMPRESSED_RGBA_BPTC_UNORM";
1509 break;
1510 case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
1511 result = "GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM";
1512 break;
1513 case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
1514 result = "GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT";
1515 break;
1516 case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
1517 result = "GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT";
1518 break;
1519 case GL_COMPRESSED_RGB8_ETC2:
1520 result = "GL_COMPRESSED_RGB8_ETC2";
1521 break;
1522 case GL_COMPRESSED_SRGB8_ETC2:
1523 result = "GL_COMPRESSED_SRGB8_ETC2";
1524 break;
1525 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
1526 result = "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2";
1527 break;
1528 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
1529 result = "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2";
1530 break;
1531 case GL_COMPRESSED_RGBA8_ETC2_EAC:
1532 result = "GL_COMPRESSED_RGBA8_ETC2_EAC";
1533 break;
1534 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
1535 result = "GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC";
1536 break;
1537 case GL_COMPRESSED_R11_EAC:
1538 result = "GL_COMPRESSED_R11_EAC";
1539 break;
1540 case GL_COMPRESSED_SIGNED_R11_EAC:
1541 result = "GL_COMPRESSED_SIGNED_R11_EAC";
1542 break;
1543 case GL_COMPRESSED_RG11_EAC:
1544 result = "GL_COMPRESSED_RG11_EAC";
1545 break;
1546 case GL_COMPRESSED_SIGNED_RG11_EAC:
1547 result = "GL_COMPRESSED_SIGNED_RG11_EAC";
1548 break;
1549
1550 default:
1551 TCU_FAIL("Unrecognized internalformat");
1552 }
1553
1554 return result;
1555 }
1556
1557 /** Returns all texture+view internalformat pairs that are valid in light of GL_ARB_texture_view specification.
1558 *
1559 * @return As described.
1560 **/
1561 TextureViewUtilities::_compatible_internalformat_pairs TextureViewUtilities::
getLegalTextureAndViewInternalformatCombinations()1562 getLegalTextureAndViewInternalformatCombinations()
1563 {
1564 _compatible_internalformat_pairs result;
1565
1566 /* Iterate over all view classes */
1567 for (int current_view_class_it = static_cast<int>(VIEW_CLASS_FIRST);
1568 current_view_class_it != static_cast<int>(VIEW_CLASS_COUNT); current_view_class_it++)
1569 {
1570 _view_class current_view_class = static_cast<_view_class>(current_view_class_it);
1571 _internalformats view_class_internalformats = getInternalformatsFromViewClass(current_view_class);
1572
1573 /* Store all combinations in the result vector */
1574 for (_internalformats_const_iterator left_iterator = view_class_internalformats.begin();
1575 left_iterator != view_class_internalformats.end(); left_iterator++)
1576 {
1577 for (_internalformats_const_iterator right_iterator = view_class_internalformats.begin();
1578 right_iterator != view_class_internalformats.end(); ++right_iterator)
1579 {
1580 result.push_back(_internalformat_pair(*left_iterator, *right_iterator));
1581 } /* for (all internalformats to be used as right-side values) */
1582 } /* for (all internalformats to be used as left-side values) */
1583 } /* for (all view classes) */
1584
1585 return result;
1586 }
1587
1588 /** Returns all valid texture+view texture targets pairs.
1589 *
1590 * @return As per description.
1591 **/
getLegalTextureAndViewTargetCombinations()1592 TextureViewUtilities::_compatible_texture_target_pairs TextureViewUtilities::getLegalTextureAndViewTargetCombinations()
1593 {
1594 _compatible_texture_target_pairs result;
1595
1596 /* Iterate over all texture targets valid for a glTextureView() call. Consider each one of them as
1597 * original texture target.
1598 */
1599 for (unsigned int n_original_texture_target = 0; n_original_texture_target < n_valid_texture_targets;
1600 ++n_original_texture_target)
1601 {
1602 const glw::GLenum original_texture_target = valid_texture_targets[n_original_texture_target];
1603
1604 /* Iterate again, but this time consider each texture target as a valid new target */
1605 for (unsigned int n_compatible_texture_target = 0; n_compatible_texture_target < n_valid_texture_targets;
1606 ++n_compatible_texture_target)
1607 {
1608 const glw::GLenum view_texture_target = valid_texture_targets[n_compatible_texture_target];
1609
1610 if (TextureViewUtilities::isLegalTextureTargetForTextureView(original_texture_target, view_texture_target))
1611 {
1612 result.push_back(_texture_target_pair(original_texture_target, view_texture_target));
1613 }
1614 } /* for (all texture targets that are potentially compatible) */
1615 } /* for (all original texture targets) */
1616
1617 return result;
1618 }
1619
1620 /** Returns major & minor version for user-specified CTS rendering context type.
1621 *
1622 * @param context_type CTS rendering context type.
1623 * @param out_major_version Deref will be used to store major version. Must not be NULL.
1624 * @param out_minor_version Deref will be used to store minor version. Must not be NULL.
1625 *
1626 **/
getMajorMinorVersionFromContextVersion(const glu::ContextType & context_type,glw::GLint * out_major_version,glw::GLint * out_minor_version)1627 void TextureViewUtilities::getMajorMinorVersionFromContextVersion(const glu::ContextType &context_type,
1628 glw::GLint *out_major_version,
1629 glw::GLint *out_minor_version)
1630 {
1631 if (context_type.getAPI() == glu::ApiType::core(4, 0))
1632 {
1633 *out_major_version = 4;
1634 *out_minor_version = 0;
1635 }
1636 else if (context_type.getAPI() == glu::ApiType::core(4, 1))
1637 {
1638 *out_major_version = 4;
1639 *out_minor_version = 1;
1640 }
1641 else if (context_type.getAPI() == glu::ApiType::core(4, 2))
1642 {
1643 *out_major_version = 4;
1644 *out_minor_version = 2;
1645 }
1646 else if (context_type.getAPI() == glu::ApiType::core(4, 3))
1647 {
1648 *out_major_version = 4;
1649 *out_minor_version = 3;
1650 }
1651 else if (context_type.getAPI() == glu::ApiType::core(4, 4))
1652 {
1653 *out_major_version = 4;
1654 *out_minor_version = 4;
1655 }
1656 else if (context_type.getAPI() == glu::ApiType::core(4, 5))
1657 {
1658 *out_major_version = 4;
1659 *out_minor_version = 5;
1660 }
1661 else if (context_type.getAPI() == glu::ApiType::core(4, 6))
1662 {
1663 *out_major_version = 4;
1664 *out_minor_version = 6;
1665 }
1666 else
1667 {
1668 TCU_FAIL("Unrecognized rendering context version");
1669 }
1670 }
1671
1672 /** Tells which sampler can be used to sample a texture defined with user-specified
1673 * internalformat.
1674 *
1675 * Supports both compressed and non-compressed internalformats.
1676 * Throws TestError exception if @param internalformat was not recognized.
1677 *
1678 * @param internalformat Internalformat to use for the query.
1679 *
1680 * @return Requested information.
1681 **/
getSamplerTypeForInternalformat(const glw::GLenum internalformat)1682 _sampler_type TextureViewUtilities::getSamplerTypeForInternalformat(const glw::GLenum internalformat)
1683 {
1684 _sampler_type result = SAMPLER_TYPE_UNDEFINED;
1685
1686 /* Compressed internalformats not supported at the moment */
1687
1688 switch (internalformat)
1689 {
1690 case GL_COMPRESSED_RED_RGTC1:
1691 case GL_COMPRESSED_SIGNED_RED_RGTC1:
1692 case GL_COMPRESSED_RG_RGTC2:
1693 case GL_COMPRESSED_SIGNED_RG_RGTC2:
1694 case GL_COMPRESSED_RGBA_BPTC_UNORM:
1695 case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
1696 case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
1697 case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
1698 case GL_DEPTH_COMPONENT16:
1699 case GL_DEPTH_COMPONENT24:
1700 case GL_DEPTH_COMPONENT32F:
1701 case GL_RGBA16:
1702 case GL_RGBA16_SNORM:
1703 case GL_RGBA16F:
1704 case GL_RGBA32F:
1705 case GL_RGBA4:
1706 case GL_RGBA8:
1707 case GL_RGBA8_SNORM:
1708 case GL_RGB10_A2:
1709 case GL_RGB16:
1710 case GL_RGB16_SNORM:
1711 case GL_RGB16F:
1712 case GL_RGB32F:
1713 case GL_RGB5_A1:
1714 case GL_RGB565:
1715 case GL_RGB8:
1716 case GL_RGB8_SNORM:
1717 case GL_RGB9_E5:
1718 case GL_RG16:
1719 case GL_RG16_SNORM:
1720 case GL_RG16F:
1721 case GL_RG32F:
1722 case GL_RG8:
1723 case GL_RG8_SNORM:
1724 case GL_R11F_G11F_B10F:
1725 case GL_R16:
1726 case GL_R16F:
1727 case GL_R16_SNORM:
1728 case GL_R32F:
1729 case GL_R8:
1730 case GL_R8_SNORM:
1731 case GL_SRGB8_ALPHA8:
1732 case GL_SRGB8:
1733 {
1734 result = SAMPLER_TYPE_FLOAT;
1735
1736 break;
1737 }
1738
1739 case GL_RGB10_A2UI:
1740 case GL_RGBA32UI:
1741 case GL_RGBA16UI:
1742 case GL_RGBA8UI:
1743 case GL_RGB16UI:
1744 case GL_RGB32UI:
1745 case GL_RGB8UI:
1746 case GL_RG16UI:
1747 case GL_RG32UI:
1748 case GL_RG8UI:
1749 case GL_R16UI:
1750 case GL_R32UI:
1751 case GL_R8UI:
1752 {
1753 result = SAMPLER_TYPE_UNSIGNED_INTEGER;
1754
1755 break;
1756 }
1757
1758 case GL_RGBA16I:
1759 case GL_RGBA32I:
1760 case GL_RGBA8I:
1761 case GL_RGB16I:
1762 case GL_RGB32I:
1763 case GL_RGB8I:
1764 case GL_RG16I:
1765 case GL_RG32I:
1766 case GL_RG8I:
1767 case GL_R16I:
1768 case GL_R32I:
1769 case GL_R8I:
1770 {
1771 result = SAMPLER_TYPE_SIGNED_INTEGER;
1772
1773 break;
1774 }
1775
1776 default:
1777 {
1778 TCU_FAIL("Unrecognized internalformat");
1779 }
1780 } /* switch (interalformat) */
1781
1782 return result;
1783 }
1784
1785 /** Tells how many bytes are required to define a texture mip-map using
1786 * user-specified internalformat and type, assuming user-defined mip-map
1787 * resolution. Compressed internalformats are NOT supported.
1788 *
1789 * Throws TestError exception if @param internalformat or @param type are
1790 * found invalid.
1791 *
1792 * @param internalformat Internalformat to use for the query.
1793 * @param type Type to use for the query.
1794 * @param width Mip-map width to use for the query.
1795 * @param height Mip-map height to use for the query.
1796 *
1797 * @return Requested information.
1798 **/
getTextureDataSize(const glw::GLenum internalformat,const glw::GLenum type,const unsigned int width,const unsigned int height)1799 unsigned int TextureViewUtilities::getTextureDataSize(const glw::GLenum internalformat, const glw::GLenum type,
1800 const unsigned int width, const unsigned int height)
1801 {
1802 unsigned int internalformat_rgba_size[4] = {0};
1803 unsigned int type_rgba_size[4] = {0};
1804 unsigned int texel_size = 0;
1805
1806 TextureViewUtilities::getComponentSizeForInternalformat(internalformat, internalformat_rgba_size);
1807 TextureViewUtilities::getComponentSizeForType(type, type_rgba_size);
1808
1809 if (internalformat_rgba_size[0] == 0)
1810 {
1811 type_rgba_size[0] = 0;
1812 }
1813
1814 if (internalformat_rgba_size[1] == 0)
1815 {
1816 type_rgba_size[1] = 0;
1817 }
1818
1819 if (internalformat_rgba_size[2] == 0)
1820 {
1821 type_rgba_size[2] = 0;
1822 }
1823
1824 if (internalformat_rgba_size[3] == 0)
1825 {
1826 type_rgba_size[3] = 0;
1827 }
1828
1829 texel_size = type_rgba_size[0] + type_rgba_size[1] + type_rgba_size[2] + type_rgba_size[3];
1830
1831 /* Current implementation assumes we do not need to use bit resolution when
1832 * preparing texel data. Make extra sure we're not wrong. */
1833 DE_ASSERT((texel_size % 8) == 0);
1834
1835 texel_size /= 8; /* bits per byte */
1836
1837 return texel_size * width * height;
1838 }
1839
1840 /** Returns a string corresponding to a GL enum describing a texture target.
1841 *
1842 * @return As per description or "[?]" if the enum was not recognized.
1843 **/
getTextureTargetString(const glw::GLenum texture_target)1844 const char *TextureViewUtilities::getTextureTargetString(const glw::GLenum texture_target)
1845 {
1846 const char *result = "[?]";
1847
1848 switch (texture_target)
1849 {
1850 case GL_TEXTURE_1D:
1851 result = "GL_TEXTURE_1D";
1852 break;
1853 case GL_TEXTURE_1D_ARRAY:
1854 result = "GL_TEXTURE_1D_ARRAY";
1855 break;
1856 case GL_TEXTURE_2D:
1857 result = "GL_TEXTURE_2D";
1858 break;
1859 case GL_TEXTURE_2D_ARRAY:
1860 result = "GL_TEXTURE_2D_ARRAY";
1861 break;
1862 case GL_TEXTURE_2D_MULTISAMPLE:
1863 result = "GL_TEXTURE_2D_MULTISAMPLE";
1864 break;
1865 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1866 result = "GL_TEXTURE_2D_MULTISAMPLE_ARRAY";
1867 break;
1868 case GL_TEXTURE_3D:
1869 result = "GL_TEXTURE_3D";
1870 break;
1871 case GL_TEXTURE_BUFFER:
1872 result = "GL_TEXTURE_BUFFER";
1873 break;
1874 case GL_TEXTURE_CUBE_MAP:
1875 result = "GL_TEXTURE_CUBE_MAP";
1876 break;
1877 case GL_TEXTURE_CUBE_MAP_ARRAY:
1878 result = "GL_TEXTURE_CUBE_MAP_ARRAY";
1879 break;
1880 case GL_TEXTURE_RECTANGLE:
1881 result = "GL_TEXTURE_RECTANGLE";
1882 break;
1883 }
1884
1885 return result;
1886 }
1887
1888 /** Returns GL type that can be used to define a texture mip-map defined
1889 * with an internalformat of @param internalformat.
1890 *
1891 * Throws TestError exception if @param internalformat was found to be invalid.
1892 *
1893 * @param internalformat Internalformat to use for the query.
1894 *
1895 * @return Requested information.
1896 **/
getTypeCompatibleWithInternalformat(const glw::GLenum internalformat)1897 glw::GLenum TextureViewUtilities::getTypeCompatibleWithInternalformat(const glw::GLenum internalformat)
1898 {
1899 glw::GLenum result = GL_NONE;
1900
1901 /* Compressed internalformats not supported at the moment */
1902
1903 switch (internalformat)
1904 {
1905 case GL_RGBA8_SNORM:
1906 case GL_RGB8_SNORM:
1907 case GL_RG8_SNORM:
1908 case GL_R8_SNORM:
1909 case GL_RGBA8I:
1910 case GL_RGB8I:
1911 case GL_RG8I:
1912 case GL_R8I:
1913 {
1914 result = GL_BYTE;
1915
1916 break;
1917 }
1918
1919 case GL_DEPTH24_STENCIL8:
1920 {
1921 result = GL_UNSIGNED_INT_24_8;
1922
1923 break;
1924 }
1925
1926 case GL_DEPTH32F_STENCIL8:
1927 {
1928 result = GL_FLOAT_32_UNSIGNED_INT_24_8_REV;
1929
1930 break;
1931 }
1932
1933 case GL_RGBA16F:
1934 case GL_RGB16F:
1935 case GL_RG16F:
1936 case GL_R16F:
1937 {
1938 result = GL_HALF_FLOAT;
1939
1940 break;
1941 }
1942
1943 case GL_DEPTH_COMPONENT32F:
1944 case GL_RGBA32F:
1945 case GL_RGB32F:
1946 case GL_RG32F:
1947 case GL_R11F_G11F_B10F:
1948 case GL_R32F:
1949 {
1950 result = GL_FLOAT;
1951
1952 break;
1953 }
1954
1955 case GL_RGBA16_SNORM:
1956 case GL_RGB16_SNORM:
1957 case GL_RG16_SNORM:
1958 case GL_R16_SNORM:
1959 {
1960 result = GL_SHORT;
1961
1962 break;
1963 }
1964
1965 case GL_RGBA4:
1966 case GL_RGBA8:
1967 case GL_RGB10_A2:
1968 case GL_RGB5_A1:
1969 case GL_RGB565:
1970 case GL_RGB8:
1971 case GL_RGB9_E5:
1972 case GL_RG8:
1973 case GL_R8:
1974 case GL_SRGB8_ALPHA8:
1975 case GL_SRGB8:
1976 case GL_RGBA8UI:
1977 case GL_RGB8UI:
1978 case GL_RG8UI:
1979 case GL_R8UI:
1980 {
1981 result = GL_UNSIGNED_BYTE;
1982
1983 break;
1984 }
1985
1986 case GL_R16I:
1987 case GL_RGBA16I:
1988 case GL_RGB16I:
1989 case GL_RG16I:
1990 {
1991 result = GL_SHORT;
1992
1993 break;
1994 }
1995
1996 case GL_DEPTH_COMPONENT16:
1997 case GL_RGBA16:
1998 case GL_RGB16:
1999 case GL_RG16:
2000 case GL_R16:
2001 case GL_RGBA16UI:
2002 case GL_RGB16UI:
2003 case GL_RG16UI:
2004 case GL_R16UI:
2005 {
2006 result = GL_UNSIGNED_SHORT;
2007
2008 break;
2009 }
2010
2011 case GL_RGBA32I:
2012 case GL_RGB32I:
2013 case GL_RG32I:
2014 case GL_R32I:
2015 {
2016 result = GL_INT;
2017
2018 break;
2019 }
2020
2021 case GL_DEPTH_COMPONENT24:
2022 case GL_RGBA32UI:
2023 case GL_RGB32UI:
2024 case GL_RG32UI:
2025 case GL_R32UI:
2026 {
2027 result = GL_UNSIGNED_INT;
2028
2029 break;
2030 }
2031
2032 case GL_RGB10_A2UI:
2033 {
2034 result = GL_UNSIGNED_INT_2_10_10_10_REV;
2035
2036 break;
2037 }
2038
2039 default:
2040 {
2041 TCU_FAIL("Unrecognized internalformat");
2042 }
2043 } /* switch (interalformat) */
2044
2045 return result;
2046 }
2047
2048 /** Tells what view class is the user-specified internalformat associated with.
2049 *
2050 * Implements Table 8.21 from OpenGL Specification 4.3
2051 *
2052 * @param internalformat Internalformat to use for the query.
2053 *
2054 * @return Requested information or VIEW_CLASS_UNDEFINED if @param internalformat
2055 * has not been recognized.
2056 **/
getViewClassForInternalformat(const glw::GLenum internalformat)2057 _view_class TextureViewUtilities::getViewClassForInternalformat(const glw::GLenum internalformat)
2058 {
2059 _view_class result = VIEW_CLASS_UNDEFINED;
2060
2061 /* Note that n_internalformat_view_compatibility_array_entries needs to be divided by 2
2062 * because the value refers to a total number of entries in the array, not to the number
2063 * of pairs that can be read.
2064 */
2065 for (int n_entry = 0; n_entry < (n_internalformat_view_compatibility_array_entries >> 1); n_entry++)
2066 {
2067 glw::GLenum array_internalformat = internalformat_view_compatibility_array[(n_entry * 2) + 0];
2068 _view_class view_class = (_view_class)internalformat_view_compatibility_array[(n_entry * 2) + 1];
2069
2070 if (array_internalformat == internalformat)
2071 {
2072 result = view_class;
2073
2074 break;
2075 }
2076 } /* for (all pairs in data array) */
2077
2078 return result;
2079 }
2080
2081 /** Initializes texture storage for either an immutable or mutable texture object,
2082 * depending on configuration of the test run the storage is to be initialized for.
2083 *
2084 * @param gl GL entry-points to use for storage initialization.
2085 * @param init_mutable_to true if a mutable texture storage should be initialized,
2086 * false to initialize immutable texture storage.
2087 * @param texture_target Texture target to be used.
2088 * @param texture_depth Depth to be used for texture storage. Only used
2089 * for texture targets that use the depth information.
2090 * @param texture_height Height to be used for texture storage. Only used
2091 * for texture targets that use the height information.
2092 * @param texture_width Width to be used for texture storage.
2093 * @param texture_internalformat Internalformat to be used for texture storage.
2094 * @param texture_format Format to be used for texture storage.
2095 * @param texture_type Type to be used for texture storage.
2096 * @param n_levels_needed Amount of mip-map levels that should be used for texture storage.
2097 * Only used for texture targets that support mip-maps.
2098 * @param n_cubemaps_needed Amount of cube-maps to be used for initialization of cube map
2099 * array texture storage. Only used if @param texture_internalformat
2100 * is set to GL_TEXTURE_CUBE_MAP_ARRAY.
2101 * @param bo_id ID of a buffer object to be used for initialization of
2102 * buffer texture storage. Only used if @param texture_internalformat
2103 * is set to GL_TEXTURE_BUFFEER.
2104 *
2105 **/
initTextureStorage(const glw::Functions & gl,bool init_mutable_to,glw::GLenum texture_target,glw::GLint texture_depth,glw::GLint texture_height,glw::GLint texture_width,glw::GLenum texture_internalformat,glw::GLenum texture_format,glw::GLenum texture_type,unsigned int n_levels_needed,unsigned int n_cubemaps_needed,glw::GLint bo_id)2106 void TextureViewUtilities::initTextureStorage(const glw::Functions &gl, bool init_mutable_to,
2107 glw::GLenum texture_target, glw::GLint texture_depth,
2108 glw::GLint texture_height, glw::GLint texture_width,
2109 glw::GLenum texture_internalformat, glw::GLenum texture_format,
2110 glw::GLenum texture_type, unsigned int n_levels_needed,
2111 unsigned int n_cubemaps_needed, glw::GLint bo_id)
2112 {
2113 const glw::GLenum cubemap_texture_targets[] = {GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
2114 GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
2115 GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z};
2116 const unsigned int n_cubemap_texture_targets = sizeof(cubemap_texture_targets) / sizeof(cubemap_texture_targets[0]);
2117
2118 /* If we're going to be initializing a multisample texture object,
2119 * determine how many samples can be used for GL_RGBA8 internalformat,
2120 * given texture target that is of our interest */
2121 glw::GLint gl_max_color_texture_samples_value = 0;
2122
2123 gl.getIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &gl_max_color_texture_samples_value);
2124 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed for GL_MAX_COLOR_TEXTURE_SAMPLES");
2125
2126 if (texture_target == GL_TEXTURE_BUFFER)
2127 {
2128 gl.texBuffer(GL_TEXTURE_BUFFER, texture_internalformat, bo_id);
2129
2130 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexBuffer() call failed for GL_TEXTURE_BUFFER target");
2131 }
2132 else if (init_mutable_to)
2133 {
2134 for (unsigned int n_level = 0; n_level < n_levels_needed; ++n_level)
2135 {
2136 /* If level != 0 and we're trying to initialize a texture target which
2137 * only accepts a single level, leave now
2138 */
2139 if (n_level != 0 &&
2140 (texture_target == GL_TEXTURE_RECTANGLE || texture_target == GL_TEXTURE_2D_MULTISAMPLE ||
2141 texture_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY || texture_target == GL_TEXTURE_BUFFER))
2142 {
2143 break;
2144 }
2145
2146 /* Initialize mutable texture storage */
2147 switch (texture_target)
2148 {
2149 case GL_TEXTURE_1D:
2150 {
2151 gl.texImage1D(texture_target, n_level, texture_internalformat, texture_width >> n_level, 0, /* border */
2152 texture_format, texture_type, DE_NULL); /* pixels */
2153
2154 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexImage1D() call failed for GL_TEXTURE_1D texture target");
2155
2156 break;
2157 }
2158
2159 case GL_TEXTURE_1D_ARRAY:
2160 case GL_TEXTURE_2D:
2161 case GL_TEXTURE_RECTANGLE:
2162 {
2163 gl.texImage2D(texture_target, n_level, texture_internalformat, texture_width >> n_level,
2164 texture_height >> n_level, 0, /* border */
2165 texture_format, texture_type, DE_NULL); /* pixels */
2166
2167 GLU_EXPECT_NO_ERROR(gl.getError(),
2168 (texture_target == GL_TEXTURE_1D_ARRAY) ?
2169 "glTexImage2D() call failed for GL_TEXTURE_1D_ARRAY texture target" :
2170 (texture_target == GL_TEXTURE_2D) ?
2171 "glTexImage2D() call failed for GL_TEXTURE_2D texture target" :
2172 "glTexImage2D() call failed for GL_TEXTURE_RECTANGLE texture target");
2173
2174 break;
2175 }
2176
2177 case GL_TEXTURE_2D_ARRAY:
2178 case GL_TEXTURE_3D:
2179 {
2180 gl.texImage3D(texture_target, n_level, texture_internalformat, texture_width >> n_level,
2181 texture_height >> n_level, texture_depth >> n_level, 0, /* border */
2182 texture_format, texture_type, DE_NULL); /* pixels */
2183
2184 GLU_EXPECT_NO_ERROR(gl.getError(),
2185 (texture_target == GL_TEXTURE_2D_ARRAY) ?
2186 "glTexImage3D() call failed for GL_TEXTURE_2D_ARRAY texture target" :
2187 "glTexImage3D() call failed for GL_TEXTURE_3D texture target");
2188
2189 break;
2190 }
2191
2192 case GL_TEXTURE_2D_MULTISAMPLE:
2193 {
2194 gl.texImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, gl_max_color_texture_samples_value,
2195 texture_internalformat, texture_width >> n_level, texture_height >> n_level,
2196 GL_TRUE); /* fixedsamplelocations */
2197
2198 GLU_EXPECT_NO_ERROR(
2199 gl.getError(),
2200 "glTexImage2DMultisample() call failed for GL_TEXTURE_2D_MULTISAMPLE texture target");
2201
2202 break;
2203 }
2204
2205 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
2206 {
2207 gl.texImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, gl_max_color_texture_samples_value,
2208 texture_internalformat, texture_width >> n_level, texture_height >> n_level,
2209 texture_depth >> n_level, GL_TRUE); /* fixedsamplelocations */
2210
2211 GLU_EXPECT_NO_ERROR(
2212 gl.getError(),
2213 "glTexImage3DMultisample() call failed for GL_TEXTURE_2D_MULTISAMPLE_ARRAY texture target");
2214
2215 break;
2216 }
2217
2218 case GL_TEXTURE_CUBE_MAP:
2219 {
2220 for (unsigned int n_cubemap_texture_target = 0; n_cubemap_texture_target < n_cubemap_texture_targets;
2221 ++n_cubemap_texture_target)
2222 {
2223 glw::GLenum cubemap_texture_target = cubemap_texture_targets[n_cubemap_texture_target];
2224
2225 gl.texImage2D(cubemap_texture_target, n_level, texture_internalformat, texture_width >> n_level,
2226 texture_height >> n_level, 0, /* border */
2227 texture_format, texture_type, DE_NULL); /* pixels */
2228
2229 GLU_EXPECT_NO_ERROR(gl.getError(),
2230 "glTexImage2D() call failed for one of the cube-map texture targets");
2231 } /* for (all cube-map texture targets) */
2232
2233 break;
2234 }
2235
2236 case GL_TEXTURE_CUBE_MAP_ARRAY:
2237 {
2238 gl.texImage3D(texture_target, n_level, texture_internalformat, texture_width >> n_level,
2239 texture_height >> n_level, 6 /* layer-faces */ * n_cubemaps_needed, 0, /* border */
2240 texture_format, texture_type, DE_NULL); /* pixels */
2241
2242 GLU_EXPECT_NO_ERROR(gl.getError(),
2243 "glTexImage3D() call failed for GL_TEXTURE_CUBE_MAP_ARRAY texture target");
2244
2245 break;
2246 }
2247
2248 default:
2249 {
2250 TCU_FAIL("Unrecognized texture target");
2251 }
2252 } /* switch (texture_target) */
2253 } /* for (all levels) */
2254 } /* if (texture_type == TEST_TEXTURE_TYPE_MUTABLE_TEXTURE_OBJECT) */
2255 else
2256 {
2257 /* Initialize immutable texture storage */
2258 switch (texture_target)
2259 {
2260 case GL_TEXTURE_1D:
2261 {
2262 gl.texStorage1D(texture_target, n_levels_needed, texture_internalformat, texture_width);
2263
2264 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage1D() call failed for GL_TEXTURE_1D texture target");
2265
2266 break;
2267 }
2268
2269 case GL_TEXTURE_1D_ARRAY:
2270 case GL_TEXTURE_2D:
2271 case GL_TEXTURE_CUBE_MAP:
2272 case GL_TEXTURE_RECTANGLE:
2273 {
2274 const unsigned n_levels = (texture_target == GL_TEXTURE_RECTANGLE) ? 1 : n_levels_needed;
2275
2276 gl.texStorage2D(texture_target, n_levels, texture_internalformat, texture_width, texture_height);
2277
2278 GLU_EXPECT_NO_ERROR(gl.getError(),
2279 (texture_target == GL_TEXTURE_1D_ARRAY) ?
2280 "glTexStorage2D() call failed for GL_TEXTURE_1D_ARRAY texture target" :
2281 (texture_target == GL_TEXTURE_2D) ?
2282 "glTexStorage2D() call failed for GL_TEXTURE_2D texture target" :
2283 (texture_target == GL_TEXTURE_CUBE_MAP) ?
2284 "glTexStorage2D() call failed for GL_TEXTURE_CUBE_MAP texture target" :
2285 "glTexStorage2D() call failed for GL_TEXTURE_RECTANGLE texture target");
2286
2287 break;
2288 }
2289
2290 case GL_TEXTURE_2D_ARRAY:
2291 case GL_TEXTURE_3D:
2292 {
2293 gl.texStorage3D(texture_target, n_levels_needed, texture_internalformat, texture_width, texture_height,
2294 texture_depth);
2295
2296 GLU_EXPECT_NO_ERROR(gl.getError(),
2297 (texture_target == GL_TEXTURE_2D_ARRAY) ?
2298 "glTexStorage3D() call failed for GL_TEXTURE_2D_ARRAY texture target" :
2299 "glTexStorage3D() call failed for GL_TEXTURE_3D texture target");
2300
2301 break;
2302 }
2303
2304 case GL_TEXTURE_2D_MULTISAMPLE:
2305 {
2306 gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, gl_max_color_texture_samples_value,
2307 texture_internalformat, texture_width, texture_height,
2308 GL_TRUE); /* fixedsamplelocations */
2309
2310 GLU_EXPECT_NO_ERROR(gl.getError(),
2311 "glTexStorage2DMultisample() call failed for GL_TEXTURE_2D_MULTISAMPLE texture target");
2312
2313 break;
2314 }
2315
2316 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
2317 {
2318 gl.texStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, gl_max_color_texture_samples_value,
2319 texture_internalformat, texture_width, texture_height, texture_depth,
2320 GL_TRUE); /* fixedsamplelocations */
2321
2322 GLU_EXPECT_NO_ERROR(
2323 gl.getError(),
2324 "glTexStorage3DMultisample() call failed for GL_TEXTURE_2D_MULTISAMPLE_ARRAY texture target");
2325
2326 break;
2327 }
2328
2329 case GL_TEXTURE_CUBE_MAP_ARRAY:
2330 {
2331 const unsigned int actual_texture_depth = 6 /* layer-faces */ * n_cubemaps_needed;
2332
2333 gl.texStorage3D(texture_target, n_levels_needed, texture_internalformat, texture_width, texture_height,
2334 actual_texture_depth);
2335
2336 GLU_EXPECT_NO_ERROR(gl.getError(),
2337 "glTexStorage3D() call failed for GL_TEXTURE_CUBE_MAP_ARRAY texture target");
2338
2339 break;
2340 }
2341
2342 default:
2343 {
2344 TCU_FAIL("Unrecognized texture target");
2345 }
2346 } /* switch (texture_target) */
2347 }
2348 }
2349
2350 /** Tells whether a parent texture object, storage of which uses @param original_internalformat
2351 * internalformat, can be used to generate a texture view using @param view_internalformat
2352 * internalformat.
2353 *
2354 * @param original_internalformat Internalformat used for parent texture object storage.
2355 * @param view_internalformat Internalformat to be used for view texture object storage.
2356 *
2357 * @return true if the internalformats are compatible, false otherwise.
2358 **/
isInternalformatCompatibleForTextureView(glw::GLenum original_internalformat,glw::GLenum view_internalformat)2359 bool TextureViewUtilities::isInternalformatCompatibleForTextureView(glw::GLenum original_internalformat,
2360 glw::GLenum view_internalformat)
2361 {
2362 const _view_class original_internalformat_view_class = getViewClassForInternalformat(original_internalformat);
2363 const _view_class view_internalformat_view_class = getViewClassForInternalformat(view_internalformat);
2364
2365 return (original_internalformat_view_class == view_internalformat_view_class);
2366 }
2367
2368 /** Tells whether user-specified internalformat is compressed.
2369 *
2370 * @param internalformat Internalformat to use for the query.
2371 *
2372 * @return true if @param internalformat is a known compressed internalformat,
2373 * false otherwise.
2374 **/
isInternalformatCompressed(const glw::GLenum internalformat)2375 bool TextureViewUtilities::isInternalformatCompressed(const glw::GLenum internalformat)
2376 {
2377 bool result = false;
2378
2379 switch (internalformat)
2380 {
2381 case GL_COMPRESSED_RED_RGTC1:
2382 case GL_COMPRESSED_SIGNED_RED_RGTC1:
2383 case GL_COMPRESSED_RG_RGTC2:
2384 case GL_COMPRESSED_SIGNED_RG_RGTC2:
2385 case GL_COMPRESSED_RGBA_BPTC_UNORM:
2386 case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
2387 case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
2388 case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
2389 case GL_COMPRESSED_RGB8_ETC2:
2390 case GL_COMPRESSED_SRGB8_ETC2:
2391 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
2392 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
2393 case GL_COMPRESSED_RGBA8_ETC2_EAC:
2394 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
2395 case GL_COMPRESSED_R11_EAC:
2396 case GL_COMPRESSED_SIGNED_R11_EAC:
2397 case GL_COMPRESSED_RG11_EAC:
2398 case GL_COMPRESSED_SIGNED_RG11_EAC:
2399 {
2400 result = true;
2401
2402 break;
2403 }
2404 } /* switch (internalformat) */
2405
2406 return result;
2407 }
2408
2409 /** Tells whether user-specified internalformat operates in sRGB color space.
2410 *
2411 * @param internalformat Internalformat to use for the query.
2412 *
2413 * @return true if @param internalformat is a known sRGB internalformat,
2414 * false otherwise.
2415 **/
isInternalformatSRGB(const glw::GLenum internalformat)2416 bool TextureViewUtilities::isInternalformatSRGB(const glw::GLenum internalformat)
2417 {
2418 return (internalformat == GL_SRGB8 || internalformat == GL_SRGB8_ALPHA8 ||
2419 internalformat == GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM);
2420 }
2421
2422 /** Tells whether user-specified internalformat is supported by OpenGL of a given version.
2423 *
2424 * @param internalformat Internalformat to use for the query.
2425 * @param major_version Major version of the rendering context.
2426 * @param minor_version Minor version of the rendering context.
2427 *
2428 * @return true if the internalformat is supported, false otherwise.
2429 **/
isInternalformatSupported(glw::GLenum internalformat,const glw::GLint major_version,const glw::GLint minor_version)2430 bool TextureViewUtilities::isInternalformatSupported(glw::GLenum internalformat, const glw::GLint major_version,
2431 const glw::GLint minor_version)
2432 {
2433 (void)major_version;
2434 /* NOTE: This function, as it stands right now, does not consider OpenGL contexts
2435 * lesser than 4.
2436 **/
2437 glw::GLint minimum_minor_version = 0;
2438
2439 DE_ASSERT(major_version >= 4);
2440
2441 switch (internalformat)
2442 {
2443 /* >= OpenGL 4.0 */
2444 case GL_RGBA32F:
2445 case GL_RGBA32I:
2446 case GL_RGBA32UI:
2447 case GL_RGBA16:
2448 case GL_RGBA16F:
2449 case GL_RGBA16I:
2450 case GL_RGBA16UI:
2451 case GL_RGBA8:
2452 case GL_RGBA8I:
2453 case GL_RGBA8UI:
2454 case GL_SRGB8_ALPHA8:
2455 case GL_RGB10_A2:
2456 case GL_RGB10_A2UI:
2457 case GL_RGB5_A1:
2458 case GL_RGBA4:
2459 case GL_R11F_G11F_B10F:
2460 case GL_RG32F:
2461 case GL_RG32I:
2462 case GL_RG32UI:
2463 case GL_RG16:
2464 case GL_RG16F:
2465 case GL_RG16I:
2466 case GL_RG16UI:
2467 case GL_RG8:
2468 case GL_RG8I:
2469 case GL_RG8UI:
2470 case GL_R32F:
2471 case GL_R32I:
2472 case GL_R32UI:
2473 case GL_R16F:
2474 case GL_R16I:
2475 case GL_R16UI:
2476 case GL_R16:
2477 case GL_R8:
2478 case GL_R8I:
2479 case GL_R8UI:
2480 case GL_RGBA16_SNORM:
2481 case GL_RGBA8_SNORM:
2482 case GL_RGB32F:
2483 case GL_RGB32I:
2484 case GL_RGB32UI:
2485 case GL_RGB16_SNORM:
2486 case GL_RGB16F:
2487 case GL_RGB16I:
2488 case GL_RGB16UI:
2489 case GL_RGB16:
2490 case GL_RGB8_SNORM:
2491 case GL_RGB8:
2492 case GL_RGB8I:
2493 case GL_RGB8UI:
2494 case GL_SRGB8:
2495 case GL_RGB9_E5:
2496 case GL_RG16_SNORM:
2497 case GL_RG8_SNORM:
2498 case GL_R16_SNORM:
2499 case GL_R8_SNORM:
2500 case GL_DEPTH_COMPONENT32F:
2501 case GL_DEPTH_COMPONENT24:
2502 case GL_DEPTH_COMPONENT16:
2503 case GL_DEPTH32F_STENCIL8:
2504 case GL_DEPTH24_STENCIL8:
2505 case GL_COMPRESSED_RED_RGTC1:
2506 case GL_COMPRESSED_SIGNED_RED_RGTC1:
2507 case GL_COMPRESSED_RG_RGTC2:
2508 case GL_COMPRESSED_SIGNED_RG_RGTC2:
2509 {
2510 /* Already covered by default value of minimum_minor_version */
2511
2512 break;
2513 }
2514
2515 /* >= OpenGL 4.2 */
2516 case GL_RGB565:
2517 case GL_COMPRESSED_RGBA_BPTC_UNORM:
2518 case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
2519 case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
2520 case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
2521 {
2522 minimum_minor_version = 2;
2523
2524 break;
2525 }
2526
2527 /* >= OpenGL 4.3 */
2528 case GL_COMPRESSED_RGB8_ETC2:
2529 case GL_COMPRESSED_SRGB8_ETC2:
2530 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
2531 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
2532 case GL_COMPRESSED_RGBA8_ETC2_EAC:
2533 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
2534 case GL_COMPRESSED_R11_EAC:
2535 case GL_COMPRESSED_SIGNED_R11_EAC:
2536 case GL_COMPRESSED_RG11_EAC:
2537 case GL_COMPRESSED_SIGNED_RG11_EAC:
2538 {
2539 minimum_minor_version = 3;
2540
2541 break;
2542 }
2543
2544 default:
2545 TCU_FAIL("Unrecognized internalformat");
2546 }
2547
2548 return (minor_version >= minimum_minor_version);
2549 }
2550
2551 /** Tells whether a parent texture object using @param original_texture_target texture target
2552 * can be used to generate a texture view of @param view_texture_target texture target.
2553 *
2554 * @param original_texture_target Texture target used by parent texture;
2555 * @param view_texture_target Texture target to be used for view texture;
2556 *
2557 * @return true if the texture targets are compatible, false otherwise.
2558 **/
isLegalTextureTargetForTextureView(glw::GLenum original_texture_target,glw::GLenum view_texture_target)2559 bool TextureViewUtilities::isLegalTextureTargetForTextureView(glw::GLenum original_texture_target,
2560 glw::GLenum view_texture_target)
2561 {
2562 bool result = false;
2563
2564 switch (original_texture_target)
2565 {
2566 case GL_TEXTURE_1D:
2567 {
2568 result = (view_texture_target == GL_TEXTURE_1D || view_texture_target == GL_TEXTURE_1D_ARRAY);
2569
2570 break;
2571 }
2572
2573 case GL_TEXTURE_2D:
2574 {
2575 result = (view_texture_target == GL_TEXTURE_2D || view_texture_target == GL_TEXTURE_2D_ARRAY);
2576
2577 break;
2578 }
2579
2580 case GL_TEXTURE_3D:
2581 {
2582 result = (view_texture_target == GL_TEXTURE_3D);
2583
2584 break;
2585 }
2586
2587 case GL_TEXTURE_CUBE_MAP:
2588 {
2589 result = (view_texture_target == GL_TEXTURE_CUBE_MAP || view_texture_target == GL_TEXTURE_2D ||
2590 view_texture_target == GL_TEXTURE_2D_ARRAY || view_texture_target == GL_TEXTURE_CUBE_MAP_ARRAY);
2591
2592 break;
2593 }
2594
2595 case GL_TEXTURE_RECTANGLE:
2596 {
2597 result = (view_texture_target == GL_TEXTURE_RECTANGLE);
2598
2599 break;
2600 }
2601
2602 case GL_TEXTURE_BUFFER:
2603 {
2604 /* No targets supported */
2605
2606 break;
2607 }
2608
2609 case GL_TEXTURE_1D_ARRAY:
2610 {
2611 result = (view_texture_target == GL_TEXTURE_1D_ARRAY || view_texture_target == GL_TEXTURE_1D);
2612
2613 break;
2614 }
2615
2616 case GL_TEXTURE_2D_ARRAY:
2617 {
2618 result = (view_texture_target == GL_TEXTURE_2D_ARRAY || view_texture_target == GL_TEXTURE_2D ||
2619 view_texture_target == GL_TEXTURE_CUBE_MAP || view_texture_target == GL_TEXTURE_CUBE_MAP_ARRAY);
2620
2621 break;
2622 }
2623
2624 case GL_TEXTURE_CUBE_MAP_ARRAY:
2625 {
2626 result = (view_texture_target == GL_TEXTURE_CUBE_MAP_ARRAY || view_texture_target == GL_TEXTURE_2D_ARRAY ||
2627 view_texture_target == GL_TEXTURE_2D || view_texture_target == GL_TEXTURE_CUBE_MAP);
2628
2629 break;
2630 }
2631
2632 case GL_TEXTURE_2D_MULTISAMPLE:
2633 {
2634 result = (view_texture_target == GL_TEXTURE_2D_MULTISAMPLE ||
2635 view_texture_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY);
2636
2637 break;
2638 }
2639
2640 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
2641 {
2642 result = (view_texture_target == GL_TEXTURE_2D_MULTISAMPLE ||
2643 view_texture_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY);
2644
2645 break;
2646 }
2647 } /* switch (original_texture_target) */
2648
2649 return result;
2650 }
2651
2652 /** Constructor.
2653 *
2654 * @param context Rendering context.
2655 **/
TextureViewTestGetTexParameter(deqp::Context & context)2656 TextureViewTestGetTexParameter::TextureViewTestGetTexParameter(deqp::Context &context)
2657 : TestCase(context, "gettexparameter",
2658 "Verifies glGetTexParameterfv() and glGetTexParameteriv() "
2659 "work as specified")
2660 {
2661 /* Left blank on purpose */
2662 }
2663
2664 /** De-initializes all GL objects created for the test. */
deinit()2665 void TextureViewTestGetTexParameter::deinit()
2666 {
2667 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2668
2669 /* Deinitialize all test runs */
2670 for (_test_runs_iterator it = m_test_runs.begin(); it != m_test_runs.end(); ++it)
2671 {
2672 _test_run &test_run = *it;
2673
2674 if (test_run.parent_texture_object_id != 0)
2675 {
2676 gl.deleteTextures(1, &test_run.parent_texture_object_id);
2677
2678 test_run.parent_texture_object_id = 0;
2679 }
2680
2681 if (test_run.texture_view_object_created_from_immutable_to_id != 0)
2682 {
2683 gl.deleteTextures(1, &test_run.texture_view_object_created_from_immutable_to_id);
2684
2685 test_run.texture_view_object_created_from_immutable_to_id = 0;
2686 }
2687
2688 if (test_run.texture_view_object_created_from_view_to_id != 0)
2689 {
2690 gl.deleteTextures(1, &test_run.texture_view_object_created_from_view_to_id);
2691
2692 test_run.texture_view_object_created_from_view_to_id = 0;
2693 }
2694 }
2695 m_test_runs.clear();
2696 }
2697
2698 /** Initializes test run descriptors used by the test. This also includes
2699 * all GL objects used by all the iterations.
2700 **/
initTestRuns()2701 void TextureViewTestGetTexParameter::initTestRuns()
2702 {
2703 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2704 const int n_cubemaps_needed = 4; /* only used for GL_TEXTURE_CUBE_MAP_ARRAY */
2705 const int texture_depth = 16;
2706 const int texture_height = 32;
2707 const int texture_width = 64;
2708
2709 const glw::GLenum texture_targets[] = {
2710 GL_TEXTURE_1D, GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D,
2711 GL_TEXTURE_2D_ARRAY, GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_2D_MULTISAMPLE_ARRAY,
2712 GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_CUBE_MAP_ARRAY,
2713 GL_TEXTURE_RECTANGLE};
2714 const _test_texture_type texture_types[] = {
2715 TEST_TEXTURE_TYPE_NO_STORAGE_ALLOCATED, TEST_TEXTURE_TYPE_IMMUTABLE_TEXTURE_OBJECT,
2716 TEST_TEXTURE_TYPE_MUTABLE_TEXTURE_OBJECT, TEST_TEXTURE_TYPE_TEXTURE_VIEW_CREATED_FROM_IMMUTABLE_TEXTURE_OBJECT,
2717 TEST_TEXTURE_TYPE_TEXTURE_VIEW_CREATED_FROM_TEXTURE_VIEW};
2718 const unsigned int n_texture_targets = sizeof(texture_targets) / sizeof(texture_targets[0]);
2719 const unsigned int n_texture_types = sizeof(texture_types) / sizeof(texture_types[0]);
2720
2721 /* Iterate through all texture types supported by the test */
2722 for (unsigned int n_texture_type = 0; n_texture_type < n_texture_types; ++n_texture_type)
2723 {
2724 const _test_texture_type texture_type = texture_types[n_texture_type];
2725
2726 /* Iterate through all texture targets supported by the test */
2727 for (unsigned int n_texture_target = 0; n_texture_target < n_texture_targets; ++n_texture_target)
2728 {
2729 _test_run new_test_run;
2730 const glw::GLenum texture_target = texture_targets[n_texture_target];
2731
2732 /* Texture buffers are neither immutable nor mutable. In order to avoid testing
2733 * them in both cases, let's assume they are immutable objects */
2734 if (texture_target == GL_TEXTURE_BUFFER && texture_type == TEST_TEXTURE_TYPE_MUTABLE_TEXTURE_OBJECT)
2735 {
2736 continue;
2737 }
2738
2739 /* Set up test run properties. Since we're only testing a single
2740 * configuration, we can set these to predefined values..
2741 */
2742 const int n_levels_needed = 6;
2743 glw::GLint n_min_layer = 1;
2744 glw::GLint n_num_layers = 2;
2745 glw::GLint n_min_level = 2;
2746 glw::GLint n_num_levels = 3;
2747 int parent_texture_depth = texture_depth;
2748 int parent_texture_height = texture_height;
2749 int parent_texture_width = texture_width;
2750
2751 new_test_run.texture_target = texture_target;
2752 new_test_run.texture_type = texture_type;
2753
2754 /* Take note of target-specific restrictions */
2755 if (texture_target == GL_TEXTURE_CUBE_MAP || texture_target == GL_TEXTURE_CUBE_MAP_ARRAY)
2756 {
2757 n_num_layers = 6 /* layer-faces */ * 2; /* as per spec */
2758
2759 /* Make sure that cube face width matches its height */
2760 parent_texture_height = 64;
2761 parent_texture_width = 64;
2762
2763 /* Also change the depth so that there's at least a few layers
2764 * we can use in the test for GL_TEXTURE_CUBE_MAP_ARRAY case
2765 */
2766 parent_texture_depth = 64;
2767 }
2768
2769 if (texture_target == GL_TEXTURE_CUBE_MAP)
2770 {
2771 /* Texture views created from a cube map texture should always
2772 * use a minimum layer of zero
2773 */
2774 n_min_layer = 0;
2775 n_num_layers = 6;
2776 }
2777
2778 if (texture_target == GL_TEXTURE_CUBE_MAP_ARRAY)
2779 {
2780 /* Slightly modify the values we'll use for <minlayer>
2781 * and <numlayers> arguments passed to glTextureView() calls
2782 * so that we can test the "view from view from texture" case
2783 */
2784 n_min_layer = 0;
2785 }
2786
2787 if (texture_target == GL_TEXTURE_1D || texture_target == GL_TEXTURE_2D ||
2788 texture_target == GL_TEXTURE_2D_MULTISAMPLE || texture_target == GL_TEXTURE_3D ||
2789 texture_target == GL_TEXTURE_RECTANGLE)
2790 {
2791 /* All these texture targets are single-layer only. glTextureView()
2792 * also requires <numlayers> argument to be set to 1 for them, so
2793 * take this into account.
2794 **/
2795 n_min_layer = 0;
2796 n_num_layers = 1;
2797 }
2798
2799 if (texture_target == GL_TEXTURE_2D_MULTISAMPLE || texture_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY ||
2800 texture_target == GL_TEXTURE_RECTANGLE)
2801 {
2802 /* All these texture targets do not support mip-maps */
2803 n_min_level = 0;
2804 }
2805
2806 /* Initialize parent texture object */
2807 gl.genTextures(1, &new_test_run.parent_texture_object_id);
2808 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed");
2809
2810 gl.bindTexture(texture_target, new_test_run.parent_texture_object_id);
2811 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
2812
2813 if (texture_type != TEST_TEXTURE_TYPE_NO_STORAGE_ALLOCATED)
2814 {
2815 TextureViewUtilities::initTextureStorage(gl, (texture_type == TEST_TEXTURE_TYPE_MUTABLE_TEXTURE_OBJECT),
2816 texture_target, parent_texture_depth, parent_texture_height,
2817 parent_texture_width, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE,
2818 n_levels_needed, n_cubemaps_needed, 0); /* bo_id */
2819 }
2820
2821 /* Update expected view-specific property values to include interactions
2822 * with immutable textures. */
2823 if (texture_type == TEST_TEXTURE_TYPE_IMMUTABLE_TEXTURE_OBJECT ||
2824 texture_type == TEST_TEXTURE_TYPE_TEXTURE_VIEW_CREATED_FROM_IMMUTABLE_TEXTURE_OBJECT ||
2825 texture_type == TEST_TEXTURE_TYPE_TEXTURE_VIEW_CREATED_FROM_TEXTURE_VIEW)
2826 {
2827 /* Set expected GL_TEXTURE_IMMUTABLE_LEVELS property value to the number
2828 * of levels we'll be using for the immutable texture storage. For selected
2829 * texture targets that do no take <levels> argument, we'll change this
2830 * value on a case-by-case basis.
2831 */
2832 new_test_run.expected_n_immutable_levels = n_levels_needed;
2833
2834 /* Set expected GL_TEXTURE_VIEW_NUM_LAYERS property value to 1, as per GL spec.
2835 * This value will be modified for selected texture targets */
2836 new_test_run.expected_n_num_layers = 1;
2837
2838 /* Configured expected GL_TEXTURE_VIEW_NUM_LEVELS value as per GL spec */
2839 new_test_run.expected_n_num_levels = n_levels_needed;
2840
2841 /* Initialize immutable texture storage */
2842 switch (texture_target)
2843 {
2844 case GL_TEXTURE_1D_ARRAY:
2845 {
2846 /* Update expected GL_TEXTURE_VIEW_NUM_LAYERS property value as per GL specification */
2847 new_test_run.expected_n_num_layers = texture_height;
2848
2849 break;
2850 }
2851
2852 case GL_TEXTURE_CUBE_MAP:
2853 {
2854 /* Update expected GL_TEXTURE_VIEW_NUM_LAYERS property value as per GL specification */
2855 new_test_run.expected_n_num_layers = 6;
2856
2857 break;
2858 }
2859
2860 case GL_TEXTURE_RECTANGLE:
2861 {
2862 new_test_run.expected_n_immutable_levels = 1;
2863 new_test_run.expected_n_num_levels = 1;
2864
2865 break;
2866 }
2867
2868 case GL_TEXTURE_2D_ARRAY:
2869 {
2870 /* Update expected GL_TEXTURE_VIEW_NUM_LAYERS property value as per GL specification */
2871 new_test_run.expected_n_num_layers = texture_depth;
2872
2873 break;
2874 }
2875
2876 case GL_TEXTURE_2D_MULTISAMPLE:
2877 {
2878 /* 2D multisample texture are not mip-mapped, so update
2879 * expected GL_TEXTURE_IMMUTABLE_LEVELS and GL_TEXTURE_VIEW_NUM_LEVELS
2880 * value accordingly */
2881 new_test_run.expected_n_immutable_levels = 1;
2882 new_test_run.expected_n_num_levels = 1;
2883
2884 break;
2885 }
2886
2887 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
2888 {
2889 /* 2D multisample array textures are not mip-mapped, so update
2890 * expected GL_TEXTURE_IMMUTABLE_LEVELS and GL_TEXTURE_VIEW_NUM_LEVELS
2891 * values accordingly */
2892 new_test_run.expected_n_immutable_levels = 1;
2893 new_test_run.expected_n_num_levels = 1;
2894
2895 /* Update expected GL_TEXTURE_VIEW_NUM_LAYERS property value as per GL specification */
2896 new_test_run.expected_n_num_layers = texture_depth;
2897
2898 break;
2899 }
2900
2901 case GL_TEXTURE_CUBE_MAP_ARRAY:
2902 {
2903 const unsigned int actual_texture_depth = 6 /* layer-faces */ * n_cubemaps_needed;
2904
2905 /* Update expected GL_TEXTURE_VIEW_NUM_LAYERS property value as per GL specification */
2906 new_test_run.expected_n_num_layers = actual_texture_depth;
2907
2908 break;
2909 }
2910 } /* switch (texture_target) */
2911 }
2912
2913 /* Initialize the view(s) */
2914 if (texture_type == TEST_TEXTURE_TYPE_TEXTURE_VIEW_CREATED_FROM_IMMUTABLE_TEXTURE_OBJECT ||
2915 texture_type == TEST_TEXTURE_TYPE_TEXTURE_VIEW_CREATED_FROM_TEXTURE_VIEW)
2916 {
2917 const unsigned int n_iterations =
2918 (texture_type == TEST_TEXTURE_TYPE_TEXTURE_VIEW_CREATED_FROM_TEXTURE_VIEW) ? 2 : 1;
2919
2920 for (unsigned int n_iteration = 0; n_iteration < n_iterations; ++n_iteration)
2921 {
2922 glw::GLuint *parent_id_ptr = (n_iteration == 0) ?
2923 &new_test_run.parent_texture_object_id :
2924 &new_test_run.texture_view_object_created_from_immutable_to_id;
2925 glw::GLuint *view_id_ptr = (n_iteration == 0) ?
2926 &new_test_run.texture_view_object_created_from_immutable_to_id :
2927 &new_test_run.texture_view_object_created_from_view_to_id;
2928
2929 gl.genTextures(1, view_id_ptr);
2930 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed");
2931
2932 gl.textureView(*view_id_ptr, new_test_run.texture_target, *parent_id_ptr,
2933 GL_RGBA8, /* use the parent texture object's internalformat */
2934 n_min_level, n_num_levels, n_min_layer, n_num_layers);
2935 GLU_EXPECT_NO_ERROR(gl.getError(), "glTextureView() call failed");
2936
2937 /* Query parent object's properties */
2938 glw::GLint parent_min_level = -1;
2939 glw::GLint parent_min_layer = -1;
2940 glw::GLint parent_num_layers = -1;
2941 glw::GLint parent_num_levels = -1;
2942 glw::GLint parent_n_immutable_levels = -1;
2943
2944 gl.bindTexture(texture_target, *parent_id_ptr);
2945 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
2946
2947 gl.getTexParameteriv(texture_target, GL_TEXTURE_IMMUTABLE_LEVELS, &parent_n_immutable_levels);
2948 GLU_EXPECT_NO_ERROR(
2949 gl.getError(),
2950 "glGetTexParameteriv() failed for GL_TEXTURE_IMMUTABLE_LEVELS pname queried for parent object");
2951
2952 gl.getTexParameteriv(texture_target, GL_TEXTURE_VIEW_MIN_LAYER, &parent_min_layer);
2953 GLU_EXPECT_NO_ERROR(
2954 gl.getError(),
2955 "glGetTexParameteriv() failed for GL_TEXTURE_VIEW_MIN_LAYER pname queried for parent object");
2956
2957 gl.getTexParameteriv(texture_target, GL_TEXTURE_VIEW_MIN_LEVEL, &parent_min_level);
2958 GLU_EXPECT_NO_ERROR(
2959 gl.getError(),
2960 "glGetTexParameteriv() failed for GL_TEXTURE_VIEW_MIN_LEVEL pname queried for parent object");
2961
2962 gl.getTexParameteriv(texture_target, GL_TEXTURE_VIEW_NUM_LAYERS, &parent_num_layers);
2963 GLU_EXPECT_NO_ERROR(
2964 gl.getError(),
2965 "glGetTexParameteriv() failed for GL_TEXTURE_VIEW_NUM_LAYERS pname queried for parent object");
2966
2967 gl.getTexParameteriv(texture_target, GL_TEXTURE_VIEW_NUM_LEVELS, &parent_num_levels);
2968 GLU_EXPECT_NO_ERROR(
2969 gl.getError(),
2970 "glGetTexParameteriv() failed for GL_TEXTURE_VIEW_NUM_LEVELS pname queried for parent object");
2971
2972 /* Update test run-specific expected values as per GL_ARB_texture_view extension specification */
2973 /*
2974 * - TEXTURE_IMMUTABLE_LEVELS is set to the value of TEXTURE_IMMUTABLE_LEVELS
2975 * from the original texture.
2976 */
2977 new_test_run.expected_n_immutable_levels = parent_n_immutable_levels;
2978
2979 /*
2980 * - TEXTURE_VIEW_MIN_LEVEL is set to <minlevel> plus the value of
2981 * TEXTURE_VIEW_MIN_LEVEL from the original texture.
2982 */
2983 new_test_run.expected_n_min_level = n_min_level + parent_min_level;
2984
2985 /*
2986 * - TEXTURE_VIEW_MIN_LAYER is set to <minlayer> plus the value of
2987 * TEXTURE_VIEW_MIN_LAYER from the original texture.
2988 */
2989 new_test_run.expected_n_min_layer = n_min_layer + parent_min_layer;
2990
2991 /*
2992 * - TEXTURE_VIEW_NUM_LAYERS is set to the lesser of <numlayers> and the
2993 * value of TEXTURE_VIEW_NUM_LAYERS from the original texture minus
2994 * <minlayer>.
2995 *
2996 */
2997 if ((parent_num_layers - n_min_layer) < n_num_layers)
2998 {
2999 new_test_run.expected_n_num_layers = parent_num_layers - n_min_layer;
3000 }
3001 else
3002 {
3003 new_test_run.expected_n_num_layers = n_num_layers;
3004 }
3005
3006 /*
3007 * - TEXTURE_VIEW_NUM_LEVELS is set to the lesser of <numlevels> and the
3008 * value of TEXTURE_VIEW_NUM_LEVELS from the original texture minus
3009 * <minlevels>.
3010 *
3011 */
3012 if ((parent_num_levels - n_min_level) < n_num_levels)
3013 {
3014 new_test_run.expected_n_num_levels = parent_num_levels - n_min_level;
3015 }
3016 else
3017 {
3018 new_test_run.expected_n_num_levels = n_num_levels;
3019 }
3020 } /* for (all iterations) */
3021 } /* if (texture_type == TEST_TEXTURE_TYPE_TEXTURE_VIEW_CREATED_FROM_IMMUTABLE_TEXTURE_OBJECT ||
3022 texture_type == TEST_TEXTURE_TYPE_TEXTURE_VIEW_CREATED_FROM_TEXTURE_VIEW) */
3023
3024 /* Store the descriptor */
3025 m_test_runs.push_back(new_test_run);
3026 } /* for (all texture targets) */
3027 } /* for (all texture types) */
3028 }
3029
3030 /** Executes test iteration.
3031 *
3032 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
3033 */
iterate()3034 tcu::TestNode::IterateResult TextureViewTestGetTexParameter::iterate()
3035 {
3036 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3037
3038 /* Make sure GL_ARB_texture_view is reported as supported before carrying on
3039 * with actual execution */
3040 const std::vector<std::string> &extensions = m_context.getContextInfo().getExtensions();
3041
3042 if (std::find(extensions.begin(), extensions.end(), "GL_ARB_texture_view") == extensions.end())
3043 {
3044 throw tcu::NotSupportedError("GL_ARB_texture_view is not supported");
3045 }
3046
3047 /* Initialize all objects necessary to execute the test */
3048 initTestRuns();
3049
3050 /* Iterate through all test runs and issue the queries */
3051 for (_test_runs_const_iterator test_run_iterator = m_test_runs.begin(); test_run_iterator != m_test_runs.end();
3052 test_run_iterator++)
3053 {
3054 glw::GLfloat query_texture_immutable_levels_value_float = -1.0f;
3055 glw::GLint query_texture_immutable_levels_value_int = -1;
3056 glw::GLfloat query_texture_view_min_layer_value_float = -1.0f;
3057 glw::GLint query_texture_view_min_layer_value_int = -1;
3058 glw::GLfloat query_texture_view_min_level_value_float = -1.0f;
3059 glw::GLint query_texture_view_min_level_value_int = -1;
3060 glw::GLfloat query_texture_view_num_layers_value_float = -1.0f;
3061 glw::GLint query_texture_view_num_layers_value_int = -1;
3062 glw::GLfloat query_texture_view_num_levels_value_float = -1.0f;
3063 glw::GLint query_texture_view_num_levels_value_int = -1;
3064 const _test_run &test_run = *test_run_iterator;
3065 glw::GLint texture_object_id = 0;
3066
3067 switch (test_run.texture_type)
3068 {
3069 case TEST_TEXTURE_TYPE_IMMUTABLE_TEXTURE_OBJECT:
3070 texture_object_id = test_run.parent_texture_object_id;
3071 break;
3072 case TEST_TEXTURE_TYPE_MUTABLE_TEXTURE_OBJECT:
3073 texture_object_id = test_run.parent_texture_object_id;
3074 break;
3075 case TEST_TEXTURE_TYPE_NO_STORAGE_ALLOCATED:
3076 texture_object_id = test_run.parent_texture_object_id;
3077 break;
3078 case TEST_TEXTURE_TYPE_TEXTURE_VIEW_CREATED_FROM_IMMUTABLE_TEXTURE_OBJECT:
3079 texture_object_id = test_run.texture_view_object_created_from_immutable_to_id;
3080 break;
3081 case TEST_TEXTURE_TYPE_TEXTURE_VIEW_CREATED_FROM_TEXTURE_VIEW:
3082 texture_object_id = test_run.texture_view_object_created_from_view_to_id;
3083 break;
3084
3085 default:
3086 {
3087 TCU_FAIL("Unrecognized texture type");
3088 }
3089 }
3090
3091 /* Bind the texture object of our interest to the target */
3092 gl.bindTexture(test_run.texture_target, texture_object_id);
3093 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
3094
3095 /* Run all the queries */
3096 gl.getTexParameterfv(test_run.texture_target, GL_TEXTURE_IMMUTABLE_LEVELS,
3097 &query_texture_immutable_levels_value_float);
3098 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexParameterfv() failed for GL_TEXTURE_IMMUTABLE_LEVELS pname");
3099
3100 gl.getTexParameteriv(test_run.texture_target, GL_TEXTURE_IMMUTABLE_LEVELS,
3101 &query_texture_immutable_levels_value_int);
3102 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexPrameteriv() failed for GL_TEXTURE_IMMUTABLE_LEVELS pname");
3103
3104 gl.getTexParameterfv(test_run.texture_target, GL_TEXTURE_VIEW_MIN_LAYER,
3105 &query_texture_view_min_layer_value_float);
3106 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexParameterfv() failed for GL_TEXTURE_VIEW_MIN_LAYER pname");
3107
3108 gl.getTexParameteriv(test_run.texture_target, GL_TEXTURE_VIEW_MIN_LAYER,
3109 &query_texture_view_min_layer_value_int);
3110 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexParameteriv() failed for GL_TEXTURE_VIEW_MIN_LAYER pname");
3111
3112 gl.getTexParameterfv(test_run.texture_target, GL_TEXTURE_VIEW_MIN_LEVEL,
3113 &query_texture_view_min_level_value_float);
3114 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexParameterfv() failed for GL_TEXTURE_VIEW_MIN_LEVEL pname");
3115
3116 gl.getTexParameteriv(test_run.texture_target, GL_TEXTURE_VIEW_MIN_LEVEL,
3117 &query_texture_view_min_level_value_int);
3118 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexParameteriv() failed for GL_TEXTURE_VIEW_MIN_LEVEL pname");
3119
3120 gl.getTexParameterfv(test_run.texture_target, GL_TEXTURE_VIEW_NUM_LAYERS,
3121 &query_texture_view_num_layers_value_float);
3122 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexParameterfv() failed for GL_TEXTURE_VIEW_NUM_LAYERS pname");
3123
3124 gl.getTexParameteriv(test_run.texture_target, GL_TEXTURE_VIEW_NUM_LAYERS,
3125 &query_texture_view_num_layers_value_int);
3126 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexParameteriv() failed for GL_TEXTURE_VIEW_NUM_LAYERS pname");
3127
3128 gl.getTexParameterfv(test_run.texture_target, GL_TEXTURE_VIEW_NUM_LEVELS,
3129 &query_texture_view_num_levels_value_float);
3130 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexParameterfv() failed for GL_TEXTURE_VIEW_NUM_LEVELS pname");
3131
3132 gl.getTexParameteriv(test_run.texture_target, GL_TEXTURE_VIEW_NUM_LEVELS,
3133 &query_texture_view_num_levels_value_int);
3134 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexParameteriv() failed for GL_TEXTURE_VIEW_NUM_LEVELS pname");
3135
3136 /* Verify the results */
3137 const float epsilon = 1e-5f;
3138
3139 if (de::abs(query_texture_immutable_levels_value_float - (float)test_run.expected_n_immutable_levels) > epsilon)
3140 {
3141 m_testCtx.getLog() << tcu::TestLog::Message
3142 << "Invalid floating-point value reported for GL_TEXTURE_IMMUTABLE_LEVELS pname "
3143 << "(expected: " << test_run.expected_n_immutable_levels
3144 << " found: " << query_texture_immutable_levels_value_float << ")."
3145 << tcu::TestLog::EndMessage;
3146
3147 TCU_FAIL("Invalid FP value reported for GL_TEXTURE_IMMUTABLE_LEVELS pname");
3148 }
3149
3150 if (query_texture_immutable_levels_value_int != test_run.expected_n_immutable_levels)
3151 {
3152 m_testCtx.getLog() << tcu::TestLog::Message
3153 << "Invalid integer value reported for GL_TEXTURE_IMMUTABLE_LEVELS pname "
3154 << "(expected: " << test_run.expected_n_immutable_levels
3155 << " found: " << query_texture_immutable_levels_value_int << ")."
3156 << tcu::TestLog::EndMessage;
3157
3158 TCU_FAIL("Invalid FP value reported for GL_TEXTURE_IMMUTABLE_LEVELS pname");
3159 }
3160
3161 if (de::abs(query_texture_view_min_layer_value_float - (float)test_run.expected_n_min_layer) > epsilon)
3162 {
3163 m_testCtx.getLog() << tcu::TestLog::Message
3164 << "Invalid floating-point value reported for GL_TEXTURE_VIEW_MIN_LAYER pname "
3165 << "(expected: " << test_run.expected_n_min_layer
3166 << " found: " << query_texture_view_min_layer_value_float << ")."
3167 << tcu::TestLog::EndMessage;
3168
3169 TCU_FAIL("Invalid FP value reported for GL_TEXTURE_VIEW_MIN_LAYER pname");
3170 }
3171
3172 if (query_texture_view_min_layer_value_int != test_run.expected_n_min_layer)
3173 {
3174 m_testCtx.getLog() << tcu::TestLog::Message
3175 << "Invalid integer value reported for GL_TEXTURE_VIEW_MIN_LAYER pname "
3176 << "(expected: " << test_run.expected_n_min_layer
3177 << " found: " << query_texture_view_min_layer_value_int << ")."
3178 << tcu::TestLog::EndMessage;
3179
3180 TCU_FAIL("Invalid FP value reported for GL_TEXTURE_VIEW_MIN_LAYER pname");
3181 }
3182
3183 if (de::abs(query_texture_view_min_level_value_float - (float)test_run.expected_n_min_level) > epsilon)
3184 {
3185 m_testCtx.getLog() << tcu::TestLog::Message
3186 << "Invalid floating-point value reported for GL_TEXTURE_VIEW_MIN_LEVEL pname "
3187 << "(expected: " << test_run.expected_n_min_level
3188 << " found: " << query_texture_view_min_level_value_float << ")."
3189 << tcu::TestLog::EndMessage;
3190
3191 TCU_FAIL("Invalid FP value reported for GL_TEXTURE_VIEW_MIN_LEVEL pname");
3192 }
3193
3194 if (query_texture_view_min_level_value_int != test_run.expected_n_min_level)
3195 {
3196 m_testCtx.getLog() << tcu::TestLog::Message
3197 << "Invalid integer value reported for GL_TEXTURE_VIEW_MIN_LEVEL pname "
3198 << "(expected: " << test_run.expected_n_min_level
3199 << " found: " << query_texture_view_min_level_value_int << ")."
3200 << tcu::TestLog::EndMessage;
3201
3202 TCU_FAIL("Invalid FP value reported for GL_TEXTURE_VIEW_MIN_LEVEL pname");
3203 }
3204
3205 if (de::abs(query_texture_view_num_layers_value_float - (float)test_run.expected_n_num_layers) > epsilon)
3206 {
3207 m_testCtx.getLog() << tcu::TestLog::Message
3208 << "Invalid floating-point value reported for GL_TEXTURE_VIEW_NUM_LAYERS pname "
3209 << "(expected: " << test_run.expected_n_num_layers
3210 << " found: " << query_texture_view_num_layers_value_float << ")."
3211 << tcu::TestLog::EndMessage;
3212
3213 TCU_FAIL("Invalid FP value reported for GL_TEXTURE_VIEW_NUM_LAYERS pname");
3214 }
3215
3216 if (query_texture_view_num_layers_value_int != test_run.expected_n_num_layers)
3217 {
3218 m_testCtx.getLog() << tcu::TestLog::Message
3219 << "Invalid integer value reported for GL_TEXTURE_VIEW_NUM_LAYERS pname "
3220 << "(expected: " << test_run.expected_n_num_layers
3221 << " found: " << query_texture_view_num_layers_value_int << ")."
3222 << tcu::TestLog::EndMessage;
3223
3224 TCU_FAIL("Invalid FP value reported for GL_TEXTURE_VIEW_NUM_LAYERS pname");
3225 }
3226
3227 if (de::abs(query_texture_view_num_levels_value_float - (float)test_run.expected_n_num_levels) > epsilon)
3228 {
3229 m_testCtx.getLog() << tcu::TestLog::Message
3230 << "Invalid floating-point value reported for GL_TEXTURE_VIEW_NUM_LEVELS pname "
3231 << "(expected: " << test_run.expected_n_num_levels
3232 << " found: " << query_texture_view_num_levels_value_float << ")."
3233 << tcu::TestLog::EndMessage;
3234
3235 TCU_FAIL("Invalid FP value reported for GL_TEXTURE_VIEW_NUM_LEVELS pname");
3236 }
3237
3238 if (query_texture_view_num_levels_value_int != test_run.expected_n_num_levels)
3239 {
3240 m_testCtx.getLog() << tcu::TestLog::Message
3241 << "Invalid integer value reported for GL_TEXTURE_VIEW_NUM_LEVELS pname "
3242 << "(expected: " << test_run.expected_n_num_levels
3243 << " found: " << query_texture_view_num_levels_value_int << ")."
3244 << tcu::TestLog::EndMessage;
3245
3246 TCU_FAIL("Invalid FP value reported for GL_TEXTURE_VIEW_NUM_LEVELS pname");
3247 }
3248 } /* for (all test runs) */
3249
3250 /* Test case passed */
3251 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3252
3253 return STOP;
3254 }
3255
3256 /** Constructor.
3257 *
3258 * @param context Rendering context
3259 **/
TextureViewTestErrors(deqp::Context & context)3260 TextureViewTestErrors::TextureViewTestErrors(deqp::Context &context)
3261 : TestCase(context, "errors", "test_description")
3262 , m_bo_id(0)
3263 , m_reference_immutable_to_1d_id(0)
3264 , m_reference_immutable_to_2d_id(0)
3265 , m_reference_immutable_to_2d_array_id(0)
3266 , m_reference_immutable_to_2d_array_32_by_33_id(0)
3267 , m_reference_immutable_to_2d_multisample_id(0)
3268 , m_reference_immutable_to_3d_id(0)
3269 , m_reference_immutable_to_cube_map_id(0)
3270 , m_reference_immutable_to_cube_map_array_id(0)
3271 , m_reference_immutable_to_rectangle_id(0)
3272 , m_reference_mutable_to_2d_id(0)
3273 , m_test_modified_to_id_1(0)
3274 , m_test_modified_to_id_2(0)
3275 , m_test_modified_to_id_3(0)
3276 , m_view_bound_to_id(0)
3277 , m_view_never_bound_to_id(0)
3278 {
3279 /* Left blank on purpose */
3280 }
3281
3282 /** Deinitializes all GL objects that may have been generated for the test. */
deinit()3283 void TextureViewTestErrors::deinit()
3284 {
3285 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3286
3287 if (m_bo_id != 0)
3288 {
3289 gl.deleteBuffers(1, &m_bo_id);
3290
3291 m_bo_id = 0;
3292 }
3293
3294 if (m_reference_immutable_to_1d_id != 0)
3295 {
3296 gl.deleteTextures(1, &m_reference_immutable_to_1d_id);
3297
3298 m_reference_immutable_to_1d_id = 0;
3299 }
3300
3301 if (m_reference_immutable_to_2d_id != 0)
3302 {
3303 gl.deleteTextures(1, &m_reference_immutable_to_2d_id);
3304
3305 m_reference_immutable_to_2d_id = 0;
3306 }
3307
3308 if (m_reference_immutable_to_2d_array_id != 0)
3309 {
3310 gl.deleteTextures(1, &m_reference_immutable_to_2d_array_id);
3311
3312 m_reference_immutable_to_2d_array_id = 0;
3313 }
3314
3315 if (m_reference_immutable_to_2d_array_32_by_33_id != 0)
3316 {
3317 gl.deleteTextures(1, &m_reference_immutable_to_2d_array_32_by_33_id);
3318
3319 m_reference_immutable_to_2d_array_32_by_33_id = 0;
3320 }
3321
3322 if (m_reference_immutable_to_2d_multisample_id != 0)
3323 {
3324 gl.deleteTextures(1, &m_reference_immutable_to_2d_multisample_id);
3325
3326 m_reference_immutable_to_2d_multisample_id = 0;
3327 }
3328
3329 if (m_reference_immutable_to_3d_id != 0)
3330 {
3331 gl.deleteTextures(1, &m_reference_immutable_to_3d_id);
3332
3333 m_reference_immutable_to_3d_id = 0;
3334 }
3335
3336 if (m_reference_immutable_to_cube_map_id != 0)
3337 {
3338 gl.deleteTextures(1, &m_reference_immutable_to_cube_map_id);
3339
3340 m_reference_immutable_to_cube_map_id = 0;
3341 }
3342
3343 if (m_reference_immutable_to_cube_map_array_id != 0)
3344 {
3345 gl.deleteTextures(1, &m_reference_immutable_to_cube_map_array_id);
3346
3347 m_reference_immutable_to_cube_map_array_id = 0;
3348 }
3349
3350 if (m_reference_immutable_to_rectangle_id != 0)
3351 {
3352 gl.deleteTextures(1, &m_reference_immutable_to_rectangle_id);
3353
3354 m_reference_immutable_to_rectangle_id = 0;
3355 }
3356
3357 if (m_reference_mutable_to_2d_id != 0)
3358 {
3359 gl.deleteTextures(1, &m_reference_mutable_to_2d_id);
3360
3361 m_reference_mutable_to_2d_id = 0;
3362 }
3363
3364 if (m_test_modified_to_id_1 != 0)
3365 {
3366 gl.deleteTextures(1, &m_test_modified_to_id_1);
3367
3368 m_test_modified_to_id_1 = 0;
3369 }
3370
3371 if (m_test_modified_to_id_2 != 0)
3372 {
3373 gl.deleteTextures(1, &m_test_modified_to_id_2);
3374
3375 m_test_modified_to_id_2 = 0;
3376 }
3377
3378 if (m_test_modified_to_id_3 != 0)
3379 {
3380 gl.deleteTextures(1, &m_test_modified_to_id_3);
3381
3382 m_test_modified_to_id_3 = 0;
3383 }
3384
3385 if (m_view_bound_to_id != 0)
3386 {
3387 gl.deleteTextures(1, &m_view_bound_to_id);
3388
3389 m_view_bound_to_id = 0;
3390 }
3391
3392 if (m_view_never_bound_to_id != 0)
3393 {
3394 gl.deleteTextures(1, &m_view_never_bound_to_id);
3395
3396 m_view_never_bound_to_id = 0;
3397 }
3398 }
3399
3400 /** Executes test iteration.
3401 *
3402 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
3403 */
iterate()3404 tcu::TestNode::IterateResult TextureViewTestErrors::iterate()
3405 {
3406 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3407
3408 /* Make sure GL_ARB_texture_view is reported as supported before carrying on
3409 * with actual execution */
3410 const std::vector<std::string> &extensions = m_context.getContextInfo().getExtensions();
3411
3412 if (std::find(extensions.begin(), extensions.end(), "GL_ARB_texture_view") == extensions.end())
3413 {
3414 throw tcu::NotSupportedError("GL_ARB_texture_view is not supported");
3415 }
3416
3417 /* Create a buffer object that we'll need to use to define storage of
3418 * buffer textures */
3419 gl.genBuffers(1, &m_bo_id);
3420 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed");
3421
3422 gl.bindBuffer(GL_TEXTURE_BUFFER, m_bo_id);
3423 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed");
3424
3425 gl.bufferData(GL_TEXTURE_BUFFER, 123, /* arbitrary size */
3426 DE_NULL, /* data */
3427 GL_STATIC_DRAW);
3428 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed");
3429
3430 /* Create reference texture objects */
3431 const glw::GLint reference_bo_id = m_bo_id;
3432 const glw::GLint reference_to_depth = 2;
3433 const glw::GLenum reference_to_format = GL_RGBA;
3434 const glw::GLint reference_to_height = 64;
3435 const glw::GLenum reference_to_internalformat = GL_RGBA32F;
3436 const glw::GLint reference_n_cubemaps = 1;
3437 const glw::GLint reference_n_levels = 1;
3438 const glw::GLenum reference_to_type = GL_FLOAT;
3439 const glw::GLint reference_to_width = 64;
3440
3441 gl.genTextures(1, &m_reference_immutable_to_1d_id);
3442 gl.genTextures(1, &m_reference_immutable_to_2d_id);
3443 gl.genTextures(1, &m_reference_immutable_to_2d_array_id);
3444 gl.genTextures(1, &m_reference_immutable_to_2d_array_32_by_33_id);
3445 gl.genTextures(1, &m_reference_immutable_to_2d_multisample_id);
3446 gl.genTextures(1, &m_reference_immutable_to_3d_id);
3447 gl.genTextures(1, &m_reference_immutable_to_cube_map_id);
3448 gl.genTextures(1, &m_reference_immutable_to_cube_map_array_id);
3449 gl.genTextures(1, &m_reference_immutable_to_rectangle_id);
3450 gl.genTextures(1, &m_reference_mutable_to_2d_id);
3451 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call(s) failed");
3452
3453 /* Retrieve GL_SAMPLES value - we'll need it to initialize multisample storage */
3454 glw::GLint gl_max_samples_value = 0;
3455
3456 gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, reference_to_internalformat, GL_SAMPLES,
3457 1 /* bufSize - first result */, &gl_max_samples_value);
3458 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetInternalformativ() failed for GL_SAMPLES pname");
3459
3460 /* Set up texture storage for single-dimensional texture object */
3461 gl.bindTexture(GL_TEXTURE_1D, m_reference_immutable_to_1d_id);
3462 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
3463
3464 gl.texStorage1D(GL_TEXTURE_1D, reference_n_levels, reference_to_internalformat, reference_to_width);
3465 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage1D() call failed");
3466
3467 /* Set up immutable texture storage for two-dimensional texture object */
3468 gl.bindTexture(GL_TEXTURE_2D, m_reference_immutable_to_2d_id);
3469 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
3470
3471 gl.texStorage2D(GL_TEXTURE_2D, reference_n_levels, reference_to_internalformat, reference_to_width,
3472 reference_to_height);
3473 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed");
3474
3475 /* Set up immutable texture storage for two-dimensional array texture object */
3476 gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_reference_immutable_to_2d_array_id);
3477 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
3478
3479 gl.texStorage3D(GL_TEXTURE_2D_ARRAY, reference_n_levels, reference_to_internalformat, reference_to_width,
3480 reference_to_height, reference_to_depth);
3481 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage3D() call failed");
3482
3483 /* Set up immutable texture storage for two-dimensional array texture object, base
3484 * level of which uses a resolution of 32x33. We'll need it to check case r) */
3485 gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_reference_immutable_to_2d_array_32_by_33_id);
3486 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
3487
3488 gl.texStorage3D(GL_TEXTURE_2D_ARRAY, reference_n_levels, reference_to_internalformat, 32, /* width */
3489 33, /* height */
3490 6); /* depth - 6 layers so that a cube-map/cube-map array view can be created from this texture */
3491 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage3D() call failed");
3492
3493 /* Set up immutable texture storage for two-dimensional multisample texture object */
3494 gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_reference_immutable_to_2d_multisample_id);
3495 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
3496
3497 gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, gl_max_samples_value, reference_to_internalformat,
3498 reference_to_width, reference_to_height, GL_TRUE); /* fixedsamplelocations */
3499 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample() call failed");
3500
3501 /* Set up immutable texture storage for three-dimensional texture object */
3502 gl.bindTexture(GL_TEXTURE_3D, m_reference_immutable_to_3d_id);
3503 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
3504
3505 gl.texStorage3D(GL_TEXTURE_3D, reference_n_levels, reference_to_internalformat, reference_to_width,
3506 reference_to_height, reference_to_depth);
3507 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage3D() call failed");
3508
3509 /* Set up immutable texture storage for cube-map texture object */
3510 gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_reference_immutable_to_cube_map_id);
3511 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
3512
3513 gl.texStorage2D(GL_TEXTURE_CUBE_MAP, reference_n_levels, reference_to_internalformat, reference_to_width,
3514 reference_to_height);
3515 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed");
3516
3517 /* Set up immutable texture storage for cube-map array texture object */
3518 gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, m_reference_immutable_to_cube_map_array_id);
3519 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
3520
3521 gl.texStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, reference_n_levels, reference_to_internalformat, reference_to_width,
3522 reference_to_height, 6 /* layer-faces */ * reference_to_depth);
3523 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed");
3524
3525 /* Set up immutable texture storage for rectangular texture object */
3526 gl.bindTexture(GL_TEXTURE_RECTANGLE, m_reference_immutable_to_rectangle_id);
3527 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
3528
3529 gl.texStorage2D(GL_TEXTURE_RECTANGLE, reference_n_levels, reference_to_internalformat, reference_to_width,
3530 reference_to_height);
3531 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed");
3532
3533 /* Set up mutable texture storage for two-dimensional texture object */
3534 gl.bindTexture(GL_TEXTURE_2D, m_reference_mutable_to_2d_id);
3535 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
3536
3537 for (glw::GLint n_level = 0; n_level < reference_n_levels; ++n_level)
3538 {
3539 gl.texImage2D(GL_TEXTURE_2D, n_level, reference_to_internalformat, reference_to_width << n_level,
3540 reference_to_height << n_level, 0, /* border */
3541 reference_to_format, reference_to_type, DE_NULL); /* pixels */
3542
3543 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexImage2D() call failed");
3544 }
3545
3546 /* Create texture objects we'll be attempting to define as texture views */
3547 gl.genTextures(1, &m_view_bound_to_id);
3548 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed");
3549
3550 gl.genTextures(1, &m_view_never_bound_to_id);
3551 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed");
3552
3553 gl.bindTexture(GL_TEXTURE_2D, m_view_bound_to_id);
3554 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
3555
3556 /* a) GL_INVALID_VALUE should be generated if <texture> is 0. */
3557 glw::GLint error_code = GL_NO_ERROR;
3558
3559 gl.textureView(0, /* texture */
3560 GL_TEXTURE_2D, m_reference_immutable_to_2d_id, reference_to_internalformat, 0, /* minlevel */
3561 reference_n_levels, 0, /* minlayer */
3562 1); /* numlayers */
3563
3564 error_code = gl.getError();
3565 if (error_code != GL_INVALID_VALUE)
3566 {
3567 m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
3568 << "]"
3569 " error generated when passing <texture> argument of 0"
3570 " to a glTextureView(), whereas GL_INVALID_VALUE was "
3571 "expected."
3572 << tcu::TestLog::EndMessage;
3573
3574 TCU_FAIL("GL_INVALID_VALUE not generated when passing 0 as <texture> argument to a "
3575 "glTextureView() call.");
3576 }
3577
3578 /* b) GL_INVALID_OPERATION should be generated if <texture> is not
3579 * a valid name returned by glGenTextures().
3580 */
3581 const glw::GLint invalid_to_id = 0xFFFFFFFF;
3582
3583 gl.textureView(invalid_to_id, GL_TEXTURE_2D, m_reference_immutable_to_2d_id, reference_to_internalformat,
3584 0, /* minlevel */
3585 reference_n_levels, 0, /* minlayer */
3586 1); /* numlayers */
3587
3588 error_code = gl.getError();
3589 if (error_code != GL_INVALID_OPERATION)
3590 {
3591 m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
3592 << "]"
3593 " error generated when passing <texture> argument of"
3594 " value that does not correspond to a valid texture "
3595 "object ID, whereas GL_INVALID_OPERATION was expected."
3596 << tcu::TestLog::EndMessage;
3597
3598 TCU_FAIL("GL_INVALID_OPERATION not generated when passing 0xFFFFFFFF as <texture> "
3599 "argument to a glTextureView() call.");
3600 }
3601
3602 /* c) GL_INVALID_OPERATION should be generated if <texture> has
3603 * already been bound and given a target.
3604 */
3605 gl.textureView(m_view_bound_to_id, GL_TEXTURE_2D, m_reference_immutable_to_2d_id, reference_to_internalformat,
3606 0, /* minlevel */
3607 reference_n_levels, 0, /* minlayer */
3608 1); /* numlayers */
3609
3610 error_code = gl.getError();
3611 if (error_code != GL_INVALID_OPERATION)
3612 {
3613 m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
3614 << "]"
3615 " error generated when passing <texture> argument "
3616 " that refers to an ID of a texture object that has "
3617 "already been bound to a texture target, whereas "
3618 "GL_INVALID_OPERATION was expected."
3619 << tcu::TestLog::EndMessage;
3620
3621 TCU_FAIL("GL_INVALID_OPERATION not generated when passing <texture> set"
3622 " to an ID of a texture object, that has already been bound to"
3623 " a texture target, to a glTextureView() call.");
3624 }
3625
3626 /* d) GL_INVALID_VALUE should be generated if <origtexture> is not
3627 * the name of a texture object.
3628 */
3629 gl.textureView(m_view_never_bound_to_id, GL_TEXTURE_2D, invalid_to_id, reference_to_internalformat,
3630 0, /* minlevel */
3631 reference_n_levels, 0, /* minlayer */
3632 1); /* numlayers */
3633
3634 error_code = gl.getError();
3635 if (error_code != GL_INVALID_VALUE)
3636 {
3637 m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
3638 << "]"
3639 " error generated when passing <origtexture> argument "
3640 " of value 0xFFFFFFFF, whereas GL_INVALID_VALUE was "
3641 "expected."
3642 << tcu::TestLog::EndMessage;
3643
3644 TCU_FAIL("GL_INVALID_VALUE not generated when passing an invalid ID of a texture "
3645 "object to <origtexture> argument.");
3646 }
3647
3648 /* e) GL_INVALID_OPERATION error should be generated if <origtexture>
3649 * is a mutable texture object.
3650 */
3651 gl.textureView(m_view_never_bound_to_id, GL_TEXTURE_2D, m_reference_mutable_to_2d_id, reference_to_internalformat,
3652 0, /* minlevel */
3653 reference_n_levels, 0, /* minlayer */
3654 1); /* numlayers */
3655
3656 error_code = gl.getError();
3657 if (error_code != GL_INVALID_OPERATION)
3658 {
3659 m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
3660 << "]"
3661 " error generated when passing <origtexture> argument "
3662 " set to refer to a mutable texture object, whereas "
3663 "GL_INVALID_OPERATION was expected."
3664 << tcu::TestLog::EndMessage;
3665
3666 TCU_FAIL("GL_INVALID_OPERATION not generated when passing an ID of a mutable "
3667 "texture object through <origtexture> argument.");
3668 }
3669
3670 /* f) GL_INVALID_OPERATION error should be generated whenever the
3671 * application tries to generate a texture view for a target
3672 * that is incompatible with original texture's target. (as per
3673 * table 8.20 from OpenGL 4.3 specification)
3674 *
3675 * NOTE: All invalid original+view texture target combinations
3676 * should be checked.
3677 */
3678 TextureViewUtilities::_incompatible_texture_target_pairs incompatible_texture_target_pairs =
3679 TextureViewUtilities::getIllegalTextureAndViewTargetCombinations();
3680
3681 for (TextureViewUtilities::_incompatible_texture_target_pairs_const_iterator pair_iterator =
3682 incompatible_texture_target_pairs.begin();
3683 pair_iterator != incompatible_texture_target_pairs.end(); pair_iterator++)
3684 {
3685 TextureViewUtilities::_internalformat_pair texture_target_pair = *pair_iterator;
3686 glw::GLenum original_texture_target = texture_target_pair.first;
3687 glw::GLenum view_texture_target = texture_target_pair.second;
3688
3689 /* Generate texture IDs */
3690 gl.genTextures(1, &m_test_modified_to_id_1);
3691 gl.genTextures(1, &m_test_modified_to_id_2);
3692 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call(s) failed");
3693
3694 /* Configure reference texture object storage */
3695 gl.bindTexture(original_texture_target, m_test_modified_to_id_1);
3696 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
3697
3698 TextureViewUtilities::initTextureStorage(gl, true, /* create mutable parent texture */
3699 original_texture_target, reference_to_depth, reference_to_height,
3700 reference_to_width, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE,
3701 reference_n_levels, reference_n_cubemaps, reference_bo_id);
3702
3703 /* Attempt to create the invalid view */
3704 gl.textureView(m_test_modified_to_id_2, /* texture */
3705 view_texture_target, m_test_modified_to_id_1, /* origtexture */
3706 reference_to_internalformat, 0, /* minlevel */
3707 reference_n_levels, 0, /* minlayer */
3708 1); /* numlayers */
3709
3710 error_code = gl.getError();
3711 if (error_code != GL_INVALID_OPERATION)
3712 {
3713 m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
3714 << "]"
3715 " error generated when passing <origtexture> argument "
3716 " set to refer to a mutable texture object, whereas "
3717 "GL_INVALID_OPERATION was expected."
3718 << tcu::TestLog::EndMessage;
3719
3720 TCU_FAIL("GL_INVALID_OPERATION not generated when passing an ID of a mutable "
3721 "texture object through <origtexture> argument.");
3722 }
3723
3724 /* Release the texture IDs */
3725 gl.deleteTextures(1, &m_test_modified_to_id_1);
3726 m_test_modified_to_id_1 = 0;
3727
3728 gl.deleteTextures(1, &m_test_modified_to_id_2);
3729 m_test_modified_to_id_2 = 0;
3730
3731 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures() call(s) failed");
3732 } /* for (all incompatible texture target pairs) */
3733
3734 /* g) GL_INVALID_OPERATION error should be generated whenever the
3735 * application tries to create a texture view, internal format
3736 * of which can be found in table 8.21 of OpenGL 4.4
3737 * specification, and the texture view's internal format is
3738 * incompatible with parent object's internal format. Both
3739 * textures and views should be used as parent objects for the
3740 * purpose of the test.
3741 *
3742 * NOTE: All invalid texture view internal formats should be
3743 * checked for all applicable original object's internal
3744 * formats
3745 */
3746 glw::GLint context_major_version = 0;
3747 glw::GLint context_minor_version = 0;
3748
3749 TextureViewUtilities::getMajorMinorVersionFromContextVersion(m_context.getRenderContext().getType(),
3750 &context_major_version, &context_minor_version);
3751
3752 TextureViewUtilities::_incompatible_internalformat_pairs internalformat_pairs =
3753 TextureViewUtilities::getIllegalTextureAndViewInternalformatCombinations();
3754
3755 for (TextureViewUtilities::_incompatible_internalformat_pairs::const_iterator pair_iterator =
3756 internalformat_pairs.begin();
3757 pair_iterator != internalformat_pairs.end(); pair_iterator++)
3758 {
3759 glw::GLenum src_internalformat = pair_iterator->first;
3760 glw::GLenum view_internalformat = pair_iterator->second;
3761
3762 /* Only run the test for internalformats supported by the tested OpenGL implementation */
3763 if (!TextureViewUtilities::isInternalformatSupported(src_internalformat, context_major_version,
3764 context_minor_version) ||
3765 !TextureViewUtilities::isInternalformatSupported(view_internalformat, context_major_version,
3766 context_minor_version))
3767 {
3768 /* Next iteration, please */
3769 continue;
3770 }
3771
3772 /* Generate texture IDs */
3773 gl.genTextures(1, &m_test_modified_to_id_1);
3774 gl.genTextures(1, &m_test_modified_to_id_2);
3775 gl.genTextures(1, &m_test_modified_to_id_3);
3776 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call(s) failed");
3777
3778 /* Configure reference texture object storage */
3779 gl.bindTexture(GL_TEXTURE_2D, m_test_modified_to_id_1);
3780 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
3781
3782 TextureViewUtilities::initTextureStorage(
3783 gl, false, /* views require immutable parent texture objects */
3784 GL_TEXTURE_2D, 0, /* texture_depth */
3785 reference_to_height, reference_to_width, src_internalformat,
3786 GL_NONE, /* texture_format - not needed for immutable texture objects */
3787 GL_NONE, /* texture_type - not needed for immutable texture objects */
3788 reference_n_levels, 0, /* n_cubemaps_needed */
3789 0); /* bo_id */
3790
3791 /* Attempt to create an invalid view */
3792 gl.textureView(m_test_modified_to_id_2, /* texture */
3793 GL_TEXTURE_2D, m_test_modified_to_id_1, /* origtexture */
3794 view_internalformat, 0, /* minlevel */
3795 reference_n_levels, 0, /* minlayer */
3796 1); /* numlayers */
3797
3798 error_code = gl.getError();
3799 if (error_code != GL_INVALID_OPERATION)
3800 {
3801 m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
3802 << "]"
3803 " error generated when requesting a view that uses "
3804 " an internalformat that is incompatible with parent "
3805 " texture object's, whereas GL_INVALID_OPERATION was "
3806 "expected."
3807 << tcu::TestLog::EndMessage;
3808
3809 TCU_FAIL("GL_INVALID_OPERATION not generated when requesting a texture view that "
3810 "uses an internalformat which is incompatible with parent texture's.");
3811 }
3812
3813 /* Create a valid view now */
3814 gl.textureView(m_test_modified_to_id_2, /* texture */
3815 GL_TEXTURE_2D, m_test_modified_to_id_1, /* origtexture */
3816 src_internalformat, 0, /* minlevel */
3817 reference_n_levels, 0, /* minlayer */
3818 1); /* numlayers */
3819
3820 GLU_EXPECT_NO_ERROR(gl.getError(), "A valid glTextureView() call failed");
3821
3822 /* Attempt to create an invalid view, using the view we've just created
3823 * as a parent */
3824 gl.textureView(m_test_modified_to_id_3, /* texture */
3825 GL_TEXTURE_2D, m_test_modified_to_id_2, /* origtexture */
3826 view_internalformat, 0, /* minlevel */
3827 reference_n_levels, 0, /* minlayer */
3828 1); /* numlayers */
3829
3830 error_code = gl.getError();
3831 if (error_code != GL_INVALID_OPERATION)
3832 {
3833 m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
3834 << "]"
3835 " error generated when requesting a view that uses "
3836 " an internalformat that is incompatible with parent "
3837 " view's, whereas GL_INVALID_OPERATION was expected."
3838 << tcu::TestLog::EndMessage;
3839
3840 TCU_FAIL("GL_INVALID_OPERATION not generated when requesting a texture view that "
3841 "uses an internalformat which is incompatible with parent view's.");
3842 }
3843
3844 /* Release the texture IDs */
3845 gl.deleteTextures(1, &m_test_modified_to_id_1);
3846 m_test_modified_to_id_1 = 0;
3847
3848 gl.deleteTextures(1, &m_test_modified_to_id_2);
3849 m_test_modified_to_id_2 = 0;
3850
3851 gl.deleteTextures(1, &m_test_modified_to_id_3);
3852 m_test_modified_to_id_3 = 0;
3853
3854 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures() call(s) failed");
3855 } /* for (all incompatible texture+view internalformat pairs) */
3856
3857 /* h) GL_INVALID_OPERATION error should be generated whenever the
3858 * application tries to create a texture view using an internal
3859 * format that does not match the original texture's, and the
3860 * original texture's internalformat cannot be found in table
3861 * 8.21 of OpenGL 4.3 specification.
3862 *
3863 * NOTE: All required base, sized and compressed texture internal
3864 * formats (as described in section 8.5.1 and table 8.14
3865 * of OpenGL 4.3 specification) that cannot be found in
3866 * table 8.21 should be considered for the purpose of this
3867 * test.
3868 */
3869 for (int n_gl_internalformat = 0; n_gl_internalformat < n_valid_gl_internalformats; ++n_gl_internalformat)
3870 {
3871 glw::GLenum parent_texture_internalformat = valid_gl_internalformats[n_gl_internalformat];
3872
3873 /* Only run the test for internalformats supported by the tested OpenGL implementation */
3874 if (!TextureViewUtilities::isInternalformatSupported(parent_texture_internalformat, context_major_version,
3875 context_minor_version))
3876 {
3877 /* Iterate the loop */
3878 continue;
3879 }
3880
3881 /* For the purpose of the test, only consider internalformats that
3882 * are not associated with any view class */
3883 if (TextureViewUtilities::getViewClassForInternalformat(parent_texture_internalformat) == VIEW_CLASS_UNDEFINED)
3884 {
3885 /* Initialize parent texture object */
3886 gl.genTextures(1, &m_test_modified_to_id_1);
3887 gl.genTextures(1, &m_test_modified_to_id_2);
3888 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call(s) failed");
3889
3890 /* Configure reference texture object storage */
3891 gl.bindTexture(GL_TEXTURE_2D, m_test_modified_to_id_1);
3892 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
3893
3894 TextureViewUtilities::initTextureStorage(
3895 gl, false, /* views require immutable parent texture objects */
3896 GL_TEXTURE_2D, 0, /* texture_depth */
3897 reference_to_height, reference_to_width, parent_texture_internalformat,
3898 GL_NONE, /* texture_format - not needed for immutable texture objects */
3899 GL_NONE, /* texture_type - not needed for immutable texture objects */
3900 reference_n_levels, 0, /* n_cubemaps_needed */
3901 0); /* bo_id */
3902
3903 /* Attempt to create the invalid view */
3904 gl.textureView(m_test_modified_to_id_2, /* texture */
3905 GL_TEXTURE_2D, m_test_modified_to_id_1, /* origtexture */
3906 (parent_texture_internalformat != GL_RGBA32F) ? GL_RGBA32F : GL_RGB32F, 0, /* minlevel */
3907 reference_n_levels, 0, /* minlayer */
3908 1); /* numlayers */
3909
3910 error_code = gl.getError();
3911 if (error_code != GL_INVALID_OPERATION)
3912 {
3913 m_testCtx.getLog() << tcu::TestLog::Message << "["
3914 << TextureViewUtilities::getErrorCodeString(error_code)
3915 << "]"
3916 " error generated when requesting a view that uses "
3917 " an internalformat different than the one used by "
3918 "parent texture object: "
3919 "["
3920 << parent_texture_internalformat
3921 << "] "
3922 " and the parent texture's internalformat is not "
3923 "associated with any view class; GL_INVALID_OPERATION "
3924 "was expected"
3925 << tcu::TestLog::EndMessage;
3926
3927 TCU_FAIL("GL_INVALID_OPERATION not generated when requesting a texture view for "
3928 "a parent texture, internalformat of which is not associated with any "
3929 "view class, when the view's internalformat is different than the one "
3930 "used for parent texture.");
3931 }
3932
3933 /* Release the texture IDs */
3934 gl.deleteTextures(1, &m_test_modified_to_id_1);
3935 m_test_modified_to_id_1 = 0;
3936
3937 gl.deleteTextures(1, &m_test_modified_to_id_2);
3938 m_test_modified_to_id_2 = 0;
3939
3940 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures() call(s) failed");
3941 } /* if (parent texture internalformat is not associated with a view class) */
3942 } /* for (all valid GL internalformats) */
3943
3944 /* i) GL_INVALID_VALUE error should be generated if <minlevel> is
3945 * larger than the greatest level of <origtexture>.
3946 */
3947 gl.textureView(m_view_never_bound_to_id, GL_TEXTURE_2D, m_reference_immutable_to_2d_id, reference_to_internalformat,
3948 reference_n_levels, /* minlevel */
3949 1, /* numlevels */
3950 0, /* minlayer */
3951 1); /* numlayers */
3952
3953 error_code = gl.getError();
3954 if (error_code != GL_INVALID_VALUE)
3955 {
3956 m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
3957 << "]"
3958 " error generated when passing <minlevel> argument "
3959 " larger than the greatest level of <origtexture>, whereas "
3960 "GL_INVALID_VALUE was expected."
3961 << tcu::TestLog::EndMessage;
3962
3963 TCU_FAIL("GL_INVALID_VALUE not generated when passing a value of <minlevel> "
3964 "larger than the greatest level defined for <origtexture>");
3965 }
3966
3967 /* j) GL_INVALID_VALUE error should be generated if <minlayer> is
3968 * larger than the greatest layer of <origtexture>.
3969 */
3970 gl.textureView(m_view_never_bound_to_id, GL_TEXTURE_2D_ARRAY, m_reference_immutable_to_2d_array_id,
3971 reference_to_internalformat, 0, /* minlevel */
3972 reference_n_levels, /* numlevels */
3973 reference_to_depth, /* minlayer */
3974 1); /* numlayers */
3975
3976 error_code = gl.getError();
3977 if (error_code != GL_INVALID_VALUE)
3978 {
3979 m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
3980 << "]"
3981 " error generated when passing <minlayer> argument "
3982 " larger than the greatest layer of <origtexture>, whereas "
3983 "GL_INVALID_VALUE was expected."
3984 << tcu::TestLog::EndMessage;
3985
3986 TCU_FAIL("GL_INVALID_VALUE not generated when passing a value of <minlayer> "
3987 "larger than the greatest layer defined for <origtexture>");
3988 }
3989
3990 /* k) GL_INVALID_VALUE error should be generated if <target> is
3991 * GL_TEXTURE_CUBE_MAP and <numlayers> is not 6.
3992 */
3993 gl.textureView(m_view_never_bound_to_id, GL_TEXTURE_CUBE_MAP, m_reference_immutable_to_cube_map_id,
3994 reference_to_internalformat, 0, /* minlevel */
3995 1, /* numlevels */
3996 0, /* minlayer */
3997 5); /* numlayers - invalid argument value */
3998
3999 error_code = gl.getError();
4000 if (error_code != GL_INVALID_VALUE)
4001 {
4002 m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
4003 << "]"
4004 " error generated when passing <numlayers> argument of value "
4005 "5 instead of 6 for GL_TEXTURE_CUBE_MAP texture target, whereas "
4006 "GL_INVALID_VALUE was expected."
4007 << tcu::TestLog::EndMessage;
4008
4009 TCU_FAIL("GL_INVALID_VALUE not generated when passing a value of 5 to <minlayer>"
4010 "argument");
4011 }
4012
4013 /* l) GL_INVALID_VALUE error should be generated if <target> is
4014 * GL_TEXTURE_CUBE_MAP_ARRAY and <numlayers> is not a multiple
4015 * of 6.
4016 */
4017 gl.textureView(m_view_never_bound_to_id, GL_TEXTURE_CUBE_MAP_ARRAY, m_reference_immutable_to_cube_map_array_id,
4018 reference_to_internalformat, 0, /* minlevel */
4019 1, /* numlevels */
4020 0, /* minlayer */
4021 1); /* numlayers - invalid argument value */
4022
4023 error_code = gl.getError();
4024 if (error_code != GL_INVALID_VALUE)
4025 {
4026 m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
4027 << "]"
4028 " error generated when passing <numlayers> argument of value "
4029 "1 instead of a multiple of 6 for GL_TEXTURE_CUBE_MAP_ARRAY "
4030 "texture target, whereas GL_INVALID_VALUE was expected."
4031 << tcu::TestLog::EndMessage;
4032
4033 TCU_FAIL("GL_INVALID_VALUE not generated when passing a value of 1 to <minlayer>"
4034 "argument for a GL_TEXTURE_CUBE_MAP_ARRAY texture target");
4035 }
4036
4037 /* m) GL_INVALID_VALUE error should be generated if <target> is
4038 * GL_TEXTURE_1D and <numlayers> is not 1;
4039 */
4040 gl.textureView(m_view_never_bound_to_id, GL_TEXTURE_1D, m_reference_immutable_to_1d_id, reference_to_internalformat,
4041 0, /* minlevel */
4042 1, /* numlevels */
4043 0, /* minlayer */
4044 2); /* numlayers - invalid argument value */
4045
4046 error_code = gl.getError();
4047 if (error_code != GL_INVALID_VALUE)
4048 {
4049 m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
4050 << "]"
4051 " error generated when passing <numlayers> argument of value "
4052 "2 instead of 1 for GL_TEXTURE_1D texture target, whereas "
4053 "GL_INVALID_VALUE was expected."
4054 << tcu::TestLog::EndMessage;
4055
4056 TCU_FAIL("GL_INVALID_VALUE not generated when passing a value of 2 to <numlayers>"
4057 "argument for a GL_TEXTURE_1D texture target");
4058 }
4059
4060 /* n) GL_INVALID_VALUE error should be generated if <target> is
4061 * GL_TEXTURE_2D and <numlayers> is not 1;
4062 */
4063 gl.textureView(m_view_never_bound_to_id, GL_TEXTURE_2D, m_reference_immutable_to_2d_id, reference_to_internalformat,
4064 0, /* minlevel */
4065 1, /* numlevels */
4066 0, /* minlayer */
4067 2); /* numlayers - invalid argument value */
4068
4069 error_code = gl.getError();
4070 if (error_code != GL_INVALID_VALUE)
4071 {
4072 m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
4073 << "]"
4074 " error generated when passing <numlayers> argument of value "
4075 "2 instead of 1 for GL_TEXTURE_2D texture target, whereas "
4076 "GL_INVALID_VALUE was expected."
4077 << tcu::TestLog::EndMessage;
4078
4079 TCU_FAIL("GL_INVALID_VALUE not generated when passing a value of 2 to <numlayers>"
4080 "argument for a GL_TEXTURE_2D texture target");
4081 }
4082
4083 /* o) GL_INVALID_VALUE error should be generated if <target> is
4084 * GL_TEXTURE_3D and <numlayers> is not 1;
4085 */
4086 gl.textureView(m_view_never_bound_to_id, GL_TEXTURE_3D, m_reference_immutable_to_3d_id, reference_to_internalformat,
4087 0, /* minlevel */
4088 1, /* numlevels */
4089 0, /* minlayer */
4090 2); /* numlayers - invalid argument value */
4091
4092 error_code = gl.getError();
4093 if (error_code != GL_INVALID_VALUE)
4094 {
4095 m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
4096 << "]"
4097 " error generated when passing <numlayers> argument of value "
4098 "2 instead of 1 for GL_TEXTURE_3D texture target, whereas "
4099 "GL_INVALID_VALUE was expected."
4100 << tcu::TestLog::EndMessage;
4101
4102 TCU_FAIL("GL_INVALID_VALUE not generated when passing a value of 2 to <numlayers>"
4103 "argument for a GL_TEXTURE_3D texture target");
4104 }
4105
4106 /* p) GL_INVALID_VALUE error should be generated if <target> is
4107 * GL_TEXTURE_RECTANGLE and <numlayers> is not 1;
4108 */
4109 gl.textureView(m_view_never_bound_to_id, GL_TEXTURE_RECTANGLE, m_reference_immutable_to_rectangle_id,
4110 reference_to_internalformat, 0, /* minlevel */
4111 1, /* numlevels */
4112 0, /* minlayer */
4113 2); /* numlayers - invalid argument value */
4114
4115 error_code = gl.getError();
4116 if (error_code != GL_INVALID_VALUE)
4117 {
4118 m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
4119 << "]"
4120 " error generated when passing <numlayers> argument of value "
4121 "2 instead of 1 for GL_TEXTURE_RECTANGLE texture target, whereas "
4122 "GL_INVALID_VALUE was expected."
4123 << tcu::TestLog::EndMessage;
4124
4125 TCU_FAIL("GL_INVALID_VALUE not generated when passing a value of 2 to <numlayers>"
4126 "argument for a GL_TEXTURE_RECTANGLE texture target");
4127 }
4128
4129 /* q) GL_INVALID_VALUE error should be generated if <target> is
4130 * GL_TEXTURE_2D_MULTISAMPLE and <numlayers> is not 1;
4131 */
4132 gl.textureView(m_view_never_bound_to_id, GL_TEXTURE_2D_MULTISAMPLE, m_reference_immutable_to_2d_multisample_id,
4133 reference_to_internalformat, 0, /* minlevel */
4134 1, /* numlevels */
4135 0, /* minlayer */
4136 2); /* numlayers - invalid argument value */
4137
4138 error_code = gl.getError();
4139 if (error_code != GL_INVALID_VALUE)
4140 {
4141 m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
4142 << "]"
4143 " error generated when passing <numlayers> argument of value "
4144 "2 instead of 1 for GL_TEXTURE_2D_MULTISAMPLE texture target, whereas "
4145 "GL_INVALID_VALUE was expected."
4146 << tcu::TestLog::EndMessage;
4147
4148 TCU_FAIL("GL_INVALID_VALUE not generated when passing a value of 2 to <numlayers>"
4149 "argument for a GL_TEXTURE_2D_MULTISAMPLE texture target");
4150 }
4151
4152 /* r) GL_INVALID_OPERATION error should be generated if <target> is
4153 * GL_TEXTURE_CUBE_MAP and original texture's width does not
4154 * match original texture's height for all levels.
4155 */
4156 gl.textureView(m_view_never_bound_to_id, GL_TEXTURE_CUBE_MAP, m_reference_immutable_to_2d_array_32_by_33_id,
4157 reference_to_internalformat, 0, /* minlevel */
4158 1, /* numlevels */
4159 0, /* minlayer */
4160 6); /* numlayers */
4161
4162 error_code = gl.getError();
4163 if (error_code != GL_INVALID_OPERATION)
4164 {
4165 m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
4166 << "]"
4167 " error generated when using an immutable 2D array texture of 32x33x6 "
4168 "resolution to generate a GL_TEXTURE_CUBE_MAP view, whereas "
4169 "GL_INVALID_OPERATION was expected."
4170 << tcu::TestLog::EndMessage;
4171
4172 TCU_FAIL("GL_INVALID_OPERATION not generated when using an immutable 2D array texture of "
4173 "32x33x6 resolution to generate a GL_TEXTURE_CUBE_MAP view");
4174 }
4175
4176 /* s) GL_INVALID_OPERATION error should be generated if <target> is
4177 * GL_TEXTURE_CUBE_MAP_ARRAY and original texture's width does
4178 * not match original texture's height for all levels.
4179 */
4180 gl.textureView(m_view_never_bound_to_id, GL_TEXTURE_CUBE_MAP_ARRAY, m_reference_immutable_to_2d_array_32_by_33_id,
4181 reference_to_internalformat, 0, /* minlevel */
4182 1, /* numlevels */
4183 0, /* minlayer */
4184 6); /* numlayers */
4185
4186 error_code = gl.getError();
4187 if (error_code != GL_INVALID_OPERATION)
4188 {
4189 m_testCtx.getLog() << tcu::TestLog::Message << "[" << TextureViewUtilities::getErrorCodeString(error_code)
4190 << "]"
4191 " error generated when using an immutable 2D array texture of 32x33x6 "
4192 "resolution to generate a GL_TEXTURE_CUBE_MAP_ARRAY view, whereas "
4193 "GL_INVALID_OPERATION was expected."
4194 << tcu::TestLog::EndMessage;
4195
4196 TCU_FAIL("GL_INVALID_OPERATION not generated when using an immutable 2D array texture of "
4197 "32x33x6 resolution to generate a GL_TEXTURE_CUBE_MAP_ARRAY view");
4198 }
4199
4200 /* Test case passed */
4201 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4202
4203 return STOP;
4204 }
4205
4206 /** Constructor.
4207 *
4208 * @param context Rendering context.
4209 **/
TextureViewTestViewSampling(deqp::Context & context)4210 TextureViewTestViewSampling::TextureViewTestViewSampling(deqp::Context &context)
4211 : TestCase(context, "view_sampling",
4212 "Verify that sampling data from texture views, that use internal "
4213 "format which is compatible with the original texture's internal "
4214 "format, works correctly.")
4215 , m_bo_id(0)
4216 , m_fs_id(0)
4217 , m_gs_id(0)
4218 , m_po_id(0)
4219 , m_po_lod_location(-1)
4220 , m_po_n_face_location(-1)
4221 , m_po_reference_colors_location(-1)
4222 , m_po_texture_location(-1)
4223 , m_po_z_float_location(-1)
4224 , m_po_z_int_location(-1)
4225 , m_tc_id(0)
4226 , m_te_id(0)
4227 , m_vs_id(0)
4228 , m_per_sample_filler_fs_id(0)
4229 , m_per_sample_filler_gs_id(0)
4230 , m_per_sample_filler_po_id(0)
4231 , m_per_sample_filler_po_layer_id_location(-1)
4232 , m_per_sample_filler_po_reference_colors_location(-1)
4233 , m_per_sample_filler_vs_id(0)
4234 , m_result_to_id(0)
4235 , m_to_id(0)
4236 , m_view_to_id(0)
4237 , m_fbo_id(0)
4238 , m_vao_id(0)
4239 , m_max_color_texture_samples_gl_value(0)
4240 , m_iteration_parent_texture_depth(0)
4241 , m_iteration_parent_texture_height(0)
4242 , m_iteration_parent_texture_n_levels(0)
4243 , m_iteration_parent_texture_n_samples(0)
4244 , m_iteration_parent_texture_target(GL_NONE)
4245 , m_iteration_parent_texture_width(0)
4246 , m_iteration_view_texture_minlayer(0)
4247 , m_iteration_view_texture_numlayers(0)
4248 , m_iteration_view_texture_minlevel(0)
4249 , m_iteration_view_texture_numlevels(0)
4250 , m_iteration_view_texture_target(GL_NONE)
4251 , m_reference_texture_depth(4)
4252 , m_reference_texture_height(4)
4253 , m_reference_texture_n_mipmaps(3)
4254 , m_reference_texture_width(4)
4255 , m_reference_color_storage(DE_NULL)
4256 , m_result_data(DE_NULL)
4257 {
4258 /* Left blank on purpose */
4259 }
4260
4261 /** De-initializes all GL objects created for the test. */
deinit()4262 void TextureViewTestViewSampling::deinit()
4263 {
4264 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4265
4266 deinitIterationSpecificProgramAndShaderObjects();
4267 deinitPerSampleFillerProgramAndShaderObjects();
4268 deinitTextureObjects();
4269
4270 /* Make sure any buffers we may have allocated during the execution do not leak */
4271 if (m_result_data != DE_NULL)
4272 {
4273 delete[] m_result_data;
4274
4275 m_result_data = DE_NULL;
4276 }
4277
4278 /* Deinitialize other objects that are not re-created every iteration */
4279 if (m_bo_id != 0)
4280 {
4281 gl.deleteBuffers(1, &m_bo_id);
4282
4283 m_bo_id = 0;
4284 }
4285
4286 if (m_fbo_id != 0)
4287 {
4288 gl.deleteFramebuffers(1, &m_fbo_id);
4289
4290 m_fbo_id = 0;
4291 }
4292
4293 if (m_reference_color_storage != DE_NULL)
4294 {
4295 delete m_reference_color_storage;
4296
4297 m_reference_color_storage = DE_NULL;
4298 }
4299
4300 if (m_vao_id != 0)
4301 {
4302 gl.deleteVertexArrays(1, &m_vao_id);
4303
4304 m_vao_id = 0;
4305 }
4306
4307 /* Restore default GL state the test may have modified */
4308 gl.patchParameteri(GL_PATCH_VERTICES, 3);
4309 gl.pixelStorei(GL_PACK_ALIGNMENT, 4);
4310 gl.pixelStorei(GL_UNPACK_ALIGNMENT, 4);
4311 }
4312
4313 /** De-initializes program and shader objects created for each iteration. **/
deinitIterationSpecificProgramAndShaderObjects()4314 void TextureViewTestViewSampling::deinitIterationSpecificProgramAndShaderObjects()
4315 {
4316 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4317
4318 if (m_fs_id != 0)
4319 {
4320 gl.deleteShader(m_fs_id);
4321
4322 m_fs_id = 0;
4323 }
4324
4325 if (m_gs_id != 0)
4326 {
4327 gl.deleteShader(m_gs_id);
4328
4329 m_gs_id = 0;
4330 }
4331
4332 if (m_po_id != 0)
4333 {
4334 gl.deleteProgram(m_po_id);
4335
4336 m_po_id = 0;
4337 }
4338
4339 if (m_tc_id != 0)
4340 {
4341 gl.deleteShader(m_tc_id);
4342
4343 m_tc_id = 0;
4344 }
4345
4346 if (m_te_id != 0)
4347 {
4348 gl.deleteShader(m_te_id);
4349
4350 m_te_id = 0;
4351 }
4352
4353 if (m_vs_id != 0)
4354 {
4355 gl.deleteShader(m_vs_id);
4356
4357 m_vs_id = 0;
4358 }
4359 }
4360
4361 /** De-initializes shader and program objects providing the 'per-sample filling'
4362 * functionality.
4363 **/
deinitPerSampleFillerProgramAndShaderObjects()4364 void TextureViewTestViewSampling::deinitPerSampleFillerProgramAndShaderObjects()
4365 {
4366 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4367
4368 if (m_per_sample_filler_fs_id != 0)
4369 {
4370 gl.deleteShader(m_per_sample_filler_fs_id);
4371
4372 m_per_sample_filler_fs_id = 0;
4373 }
4374
4375 if (m_per_sample_filler_gs_id != 0)
4376 {
4377 gl.deleteShader(m_per_sample_filler_gs_id);
4378
4379 m_per_sample_filler_gs_id = 0;
4380 }
4381
4382 if (m_per_sample_filler_po_id != 0)
4383 {
4384 gl.deleteProgram(m_per_sample_filler_po_id);
4385
4386 m_per_sample_filler_po_id = 0;
4387 }
4388
4389 if (m_per_sample_filler_vs_id != 0)
4390 {
4391 gl.deleteShader(m_per_sample_filler_vs_id);
4392
4393 m_per_sample_filler_vs_id = 0;
4394 }
4395 }
4396
4397 /** De-initializes texture objects used by the test */
deinitTextureObjects()4398 void TextureViewTestViewSampling::deinitTextureObjects()
4399 {
4400 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4401
4402 if (m_result_to_id != 0)
4403 {
4404 gl.deleteTextures(1, &m_result_to_id);
4405
4406 m_result_to_id = 0;
4407 }
4408
4409 if (m_to_id != 0)
4410 {
4411 gl.deleteTextures(1, &m_to_id);
4412
4413 m_to_id = 0;
4414 }
4415
4416 if (m_view_to_id != 0)
4417 {
4418 gl.deleteTextures(1, &m_view_to_id);
4419
4420 m_view_to_id = 0;
4421 }
4422 }
4423
4424 /** Executes a single test iteration.
4425 *
4426 * @return true if the iteration executed successfully, false otherwise.
4427 **/
executeTest()4428 bool TextureViewTestViewSampling::executeTest()
4429 {
4430 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4431 bool result = true;
4432
4433 /* Bind the view to zero texture unit */
4434 gl.activeTexture(GL_TEXTURE0);
4435 GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture() call failed.");
4436
4437 gl.bindTexture(m_iteration_view_texture_target, m_view_to_id);
4438 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
4439
4440 /* Bind the buffer object to zero TF binding point */
4441 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_bo_id);
4442 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
4443
4444 /* Activate the test program */
4445 gl.useProgram(m_po_id);
4446 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
4447
4448 /* Update draw framebuffer configuration so that the test's fragment shader draws
4449 * to the result texture */
4450 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
4451 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed.");
4452
4453 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_result_to_id, 0); /* level */
4454 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
4455
4456 /* Allocate enough space to hold reference color data for all sample s*/
4457 float *reference_color_data = new float[m_iteration_parent_texture_n_samples * sizeof(float) * 4 /* rgba */];
4458
4459 /* Iterate through the layer/face/mipmap hierarchy. For each iteration, we
4460 * potentially need to update relevant uniforms controlling the sampling process
4461 * the test program object performs.
4462 */
4463 bool is_view_cm_cma = (m_iteration_view_texture_target == GL_TEXTURE_CUBE_MAP ||
4464 m_iteration_view_texture_target == GL_TEXTURE_CUBE_MAP_ARRAY);
4465
4466 for (unsigned int n_current_layer = m_iteration_view_texture_minlayer;
4467 n_current_layer < (m_iteration_view_texture_minlayer + m_iteration_view_texture_numlayers) && result;
4468 n_current_layer++)
4469 {
4470 unsigned int n_texture_face = 0;
4471 unsigned int n_texture_layer = 0;
4472 unsigned int n_view_face = 0;
4473 unsigned int n_view_layer = 0;
4474
4475 if (is_view_cm_cma)
4476 {
4477 n_texture_face = n_current_layer % 6; /* faces */
4478 n_texture_layer = n_current_layer / 6; /* faces */
4479 n_view_face = (n_current_layer - m_iteration_view_texture_minlayer) % 6; /* faces */
4480 n_view_layer = (n_current_layer - m_iteration_view_texture_minlayer) / 6; /* faces */
4481 }
4482 else
4483 {
4484 /* Only cube-map and cube-map array textures consist of faces. */
4485 n_texture_face = 0;
4486 n_texture_layer = n_current_layer;
4487 n_view_face = 0;
4488 n_view_layer = n_current_layer;
4489 }
4490
4491 if (m_po_z_float_location != -1)
4492 {
4493 float z = 0.0f;
4494
4495 if (((false == is_view_cm_cma) && (m_iteration_view_texture_numlayers > 1)) ||
4496 ((true == is_view_cm_cma) && (m_iteration_view_texture_numlayers > 6)))
4497 {
4498 if (is_view_cm_cma)
4499 {
4500 z = float(n_view_layer) / float(m_iteration_view_texture_numlayers / 6 - 1);
4501 }
4502 else
4503 {
4504 if (m_iteration_view_texture_numlayers > 1)
4505 {
4506 /* The program will be sampling a view so make sure that layer the shader accesses
4507 * is relative to how our view was configured */
4508 z = float(n_view_layer - m_iteration_view_texture_minlayer) /
4509 float(m_iteration_view_texture_numlayers - 1);
4510 }
4511 else
4512 {
4513 /* z should stay at 0 */
4514 }
4515 }
4516 }
4517 else
4518 {
4519 /* z should stay at 0.0 */
4520 }
4521
4522 gl.uniform1f(m_po_z_float_location, z);
4523 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1f() call failed.");
4524 }
4525
4526 if (m_po_z_int_location != -1)
4527 {
4528 DE_ASSERT(!is_view_cm_cma);
4529
4530 gl.uniform1i(m_po_z_int_location, n_current_layer - m_iteration_view_texture_minlayer);
4531 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i() call failed.");
4532 }
4533
4534 if (m_po_n_face_location != -1)
4535 {
4536 gl.uniform1i(m_po_n_face_location, n_view_face);
4537 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i() call failed.");
4538 }
4539
4540 for (unsigned int n_mipmap = m_iteration_view_texture_minlevel;
4541 n_mipmap < (m_iteration_view_texture_minlevel + m_iteration_view_texture_numlevels) && result; n_mipmap++)
4542 {
4543 if (m_po_lod_location != -1)
4544 {
4545 /* The program will be sampling a view so make sure that LOD the shader accesses
4546 * is relative to how our view was configured.
4547 */
4548 gl.uniform1f(m_po_lod_location, (float)(n_mipmap - m_iteration_view_texture_minlevel));
4549 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i() call failed.");
4550 }
4551
4552 /* Update local reference color data storage */
4553 for (unsigned int n_sample = 0; n_sample < m_iteration_parent_texture_n_samples; ++n_sample)
4554 {
4555 tcu::Vec4 reference_color = getReferenceColor(n_texture_layer, n_texture_face, n_mipmap, n_sample);
4556
4557 reference_color_data[4 /* rgba */ * n_sample + 0] = reference_color.x();
4558 reference_color_data[4 /* rgba */ * n_sample + 1] = reference_color.y();
4559 reference_color_data[4 /* rgba */ * n_sample + 2] = reference_color.z();
4560 reference_color_data[4 /* rgba */ * n_sample + 3] = reference_color.w();
4561 }
4562
4563 /* Upload it to GPU */
4564 gl.uniform4fv(m_po_reference_colors_location, m_iteration_parent_texture_n_samples, reference_color_data);
4565 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4fv() call failed.");
4566
4567 /* Bind the texture view to sample from */
4568 gl.bindTexture(m_iteration_view_texture_target, m_view_to_id);
4569 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
4570
4571 /* Draw a single patch. Given the rendering pipeline we've defined in the
4572 * test program object, this should give us a nice full-screen quad, as well
4573 * as 6*4 ints XFBed out, describing whether the view was sampled correctly.
4574 */
4575 gl.beginTransformFeedback(GL_TRIANGLES);
4576 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
4577 {
4578 gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
4579 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
4580 }
4581 gl.endTransformFeedback();
4582 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
4583
4584 /* In order to verify if the texel data was sampled correctly, we need to do two things:
4585 *
4586 * 1) Verify buffer object contents;
4587 * 2) Make sure that all texels of current render-target are vec4(1).
4588 *
4589 */
4590 const int *bo_storage_ptr = (const int *)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
4591
4592 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
4593 if (bo_storage_ptr == NULL)
4594 {
4595 TCU_FAIL("glMapBuffer() call succeeded but the pointer returned is NULL");
4596 }
4597
4598 /* The rendering pipeline should have written 6 vertices * 4 ints to the BO.
4599 * The integers are set to 1 if the sampled texels were found valid, 0 otherwise,
4600 * and are arranged in the following order:
4601 *
4602 * 1) Result of sampling in vertex shader stage;
4603 * 2) Result of sampling in tessellation control shader stage;
4604 * 3) Result of sampling in tessellation evaluation shader stage;
4605 * 4) Result of sampling in geometry shader stage;
4606 */
4607 for (unsigned int n_vertex = 0; n_vertex < 6 /* as per comment */ && result; ++n_vertex)
4608 {
4609 const int *vertex_data_ptr = bo_storage_ptr + n_vertex * 4 /* as per comment */;
4610 int vs_result = vertex_data_ptr[0];
4611 int tc_result = vertex_data_ptr[1];
4612 int te_result = vertex_data_ptr[2];
4613 int gs_result = vertex_data_ptr[3];
4614
4615 if (vs_result != 1)
4616 {
4617 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid data was sampled in vertex shader stage."
4618 << tcu::TestLog::EndMessage;
4619
4620 result = false;
4621 }
4622
4623 if (tc_result != 1)
4624 {
4625 m_testCtx.getLog() << tcu::TestLog::Message
4626 << "Invalid data was sampled in tessellation control shader stage."
4627 << tcu::TestLog::EndMessage;
4628
4629 result = false;
4630 }
4631
4632 if (te_result != 1)
4633 {
4634 m_testCtx.getLog() << tcu::TestLog::Message
4635 << "Invalid data was sampled in tessellation evaluation shader stage."
4636 << tcu::TestLog::EndMessage;
4637
4638 result = false;
4639 }
4640
4641 if (gs_result != 1)
4642 {
4643 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid data was sampled in geometry shader stage."
4644 << tcu::TestLog::EndMessage;
4645
4646 result = false;
4647 }
4648 } /* for (all vertices) */
4649
4650 /* Unmap the BO */
4651 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
4652 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
4653
4654 /* Read texels rendered by the fragment shader. The texture attached uses
4655 * GL_RGBA8 internalformat.*/
4656 m_result_data = new unsigned char[m_reference_texture_width * m_reference_texture_height * 4 /* RGBA */];
4657
4658 gl.bindTexture(GL_TEXTURE_2D, m_result_to_id);
4659 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed for GL_TEXTURE_2D texture target.");
4660
4661 gl.getTexImage(GL_TEXTURE_2D, 0 /* level */, GL_RGBA, GL_UNSIGNED_BYTE, m_result_data);
4662 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexImage() call failed.");
4663
4664 /* The test fails if any of the fragments is not equal to vec4(1) */
4665 bool fs_result = true;
4666
4667 for (unsigned int y = 0; y < m_reference_texture_height && fs_result; ++y)
4668 {
4669 const unsigned char *row_ptr = m_result_data + m_reference_texture_width * y * 4 /* RGBA */;
4670
4671 for (unsigned int x = 0; x < m_reference_texture_width && fs_result; ++x)
4672 {
4673 const unsigned char *pixel_ptr = row_ptr + x * 4 /* RGBA */;
4674
4675 if (pixel_ptr[0] != 255 || pixel_ptr[1] != 255 || pixel_ptr[2] != 255 || pixel_ptr[3] != 255)
4676 {
4677 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid data was sampled at (" << x << ", " << y
4678 << ") "
4679 "in fragment shader stage."
4680 << tcu::TestLog::EndMessage;
4681
4682 fs_result = false;
4683 }
4684 } /* for (all columns) */
4685 } /* for (all rows) */
4686
4687 if (!fs_result)
4688 {
4689 result = false;
4690 }
4691
4692 /* Done - we can release the buffer at this point */
4693 delete[] m_result_data;
4694 m_result_data = DE_NULL;
4695 } /* for (all mip-maps) */
4696 } /* for (all texture layers) */
4697
4698 /* Release the reference color data buffer */
4699 delete[] reference_color_data;
4700 reference_color_data = DE_NULL;
4701
4702 /* All done */
4703 return result;
4704 }
4705
4706 /** Returns a different vec4 every time the function is called. Each component
4707 * is assigned a normalized value within <0, 1> range.
4708 *
4709 * @return As per description.
4710 **/
getRandomReferenceColor()4711 tcu::Vec4 TextureViewTestViewSampling::getRandomReferenceColor()
4712 {
4713 static unsigned int seed = 195;
4714 tcu::Vec4 result;
4715
4716 result = tcu::Vec4(float((seed) % 255) / 255.0f, float((seed << 3) % 255) / 255.0f,
4717 float((seed << 4) % 255) / 255.0f, float((seed << 5) % 255) / 255.0f);
4718
4719 seed += 17;
4720
4721 return result;
4722 }
4723
4724 /** Every test iteration is assigned a different set of so-called reference colors.
4725 * Depending on the texture target, each reference color corresponds to an unique color
4726 * used to build different layers/faces/mip-maps or even samples of tose.
4727 *
4728 * Once the reference color storage is initialized, this function can be used to retrieve
4729 * details of a color allocated a specific sample of a layer/face mip-map.
4730 *
4731 * This function will cause an assertion failure if an invalid layer/face/mipmap/sample is
4732 * requested, as well as if the reference color storage is not initialized at the time of the call.
4733 *
4734 * @param n_layer Layer index to use for the query. A value of 0 should be used for non-arrayed
4735 * texture targets.
4736 * @param n_face Face index to use for the query. A value of 0 should be used for non-CM texture
4737 * targets. Otherwise:
4738 * * 0 corresponds to +X;
4739 * * 1 corresponds to -X;
4740 * * 2 corresponds to +Y;
4741 * * 3 corresponds to -Y;
4742 * * 4 corresponds to +Z;
4743 * * 5 corresponds to -Z.
4744 * @param n_mipmap Mip-map index to use for the query. A value of 0 should be used for non-mipmapped
4745 * texture targets.
4746 * @param n_sample Sample index to use for the query. A value of 0 should be used for single-sampled
4747 * texture targets.
4748 *
4749 * @return Requested color data.
4750 **/
getReferenceColor(unsigned int n_layer,unsigned int n_face,unsigned int n_mipmap,unsigned int n_sample)4751 tcu::Vec4 TextureViewTestViewSampling::getReferenceColor(unsigned int n_layer, unsigned int n_face,
4752 unsigned int n_mipmap, unsigned int n_sample)
4753 {
4754 tcu::Vec4 result;
4755
4756 DE_ASSERT(m_reference_color_storage != DE_NULL);
4757 if (m_reference_color_storage != DE_NULL)
4758 {
4759 bool is_parent_texture_cm_cma = (m_iteration_parent_texture_target == GL_TEXTURE_CUBE_MAP ||
4760 m_iteration_parent_texture_target == GL_TEXTURE_CUBE_MAP_ARRAY);
4761 bool is_view_texture_cm_cma = (m_iteration_view_texture_target == GL_TEXTURE_CUBE_MAP ||
4762 m_iteration_view_texture_target == GL_TEXTURE_CUBE_MAP_ARRAY);
4763
4764 if (is_view_texture_cm_cma && !is_parent_texture_cm_cma)
4765 {
4766 /* Parent texture is not using faces. Compute layer index, as
4767 * if the texture was actually a CM or a CMA */
4768 unsigned int temp = n_layer * 6 /* layer-faces per layer */ + n_face;
4769
4770 n_layer = temp;
4771 n_face = 0;
4772 }
4773 else if (!is_view_texture_cm_cma && is_parent_texture_cm_cma)
4774 {
4775 /* The other way around - assume the texture is a CM or CMA */
4776 n_face = n_layer % 6; /* faces per cube-map layer */
4777 n_layer = n_layer / 6; /* faces per cube-map layer */
4778 }
4779
4780 DE_ASSERT(n_face < m_reference_color_storage->n_faces);
4781 DE_ASSERT(n_layer < m_reference_color_storage->n_layers);
4782 DE_ASSERT(n_mipmap < m_reference_color_storage->n_mipmaps);
4783 DE_ASSERT(n_sample < m_reference_color_storage->n_samples);
4784
4785 /* Hierarchy is:
4786 *
4787 * layers -> faces -> mipmaps -> samples */
4788 const unsigned int index =
4789 n_layer * (m_reference_color_storage->n_faces * m_reference_color_storage->n_mipmaps *
4790 m_reference_color_storage->n_samples) +
4791 n_face * (m_reference_color_storage->n_mipmaps * m_reference_color_storage->n_samples) +
4792 n_mipmap * (m_reference_color_storage->n_samples) + n_sample;
4793
4794 result = m_reference_color_storage->data[index];
4795 }
4796
4797 return result;
4798 }
4799
4800 /* Retrieve max conformant sample count when GL_NV_internalformat_sample_query is supported */
getMaxConformantSampleCount(glw::GLenum target,glw::GLenum internalFormat)4801 glw::GLint TextureViewTestViewSampling::getMaxConformantSampleCount(glw::GLenum target, glw::GLenum internalFormat)
4802 {
4803 (void)internalFormat;
4804 glw::GLint max_conformant_samples = 0;
4805
4806 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4807
4808 /* Return the max conformant sample count if extension is supported */
4809 if (m_context.getContextInfo().isExtensionSupported("GL_NV_internalformat_sample_query"))
4810 {
4811 glw::GLint gl_sample_counts = 0;
4812 gl.getInternalformativ(target, GL_RGBA8, GL_NUM_SAMPLE_COUNTS, 1, &gl_sample_counts);
4813 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetInternalformativ() failed for GL_NUM_SAMPLE_COUNTS pname");
4814
4815 /* Check and return the first conformant sample count */
4816 glw::GLint *gl_supported_samples = new glw::GLint[gl_sample_counts];
4817 if (gl_supported_samples)
4818 {
4819 gl.getInternalformativ(target, GL_RGBA8, GL_SAMPLES, gl_sample_counts, gl_supported_samples);
4820
4821 for (glw::GLint i = 0; i < gl_sample_counts; i++)
4822 {
4823 glw::GLint isConformant = 0;
4824 gl.getInternalformatSampleivNV(target, GL_RGBA8, gl_supported_samples[i], GL_CONFORMANT_NV, 1,
4825 &isConformant);
4826 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetInternalformatSampleivNV() call(s) failed");
4827
4828 if (isConformant && gl_supported_samples[i] > max_conformant_samples)
4829 {
4830 max_conformant_samples = gl_supported_samples[i];
4831 }
4832 }
4833 delete[] gl_supported_samples;
4834 }
4835 }
4836 else
4837 {
4838 /* Otherwise return GL_MAX_COLOR_TEXTURE_SAMPLES */
4839 gl.getIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &max_conformant_samples);
4840 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed for GL_MAX_COLOR_TEXTURE_SAMPLES pname.");
4841 }
4842
4843 return max_conformant_samples;
4844 }
4845
4846 /** Initializes iteration-specific program object used to sample the texture data. */
initIterationSpecificProgramObject()4847 void TextureViewTestViewSampling::initIterationSpecificProgramObject()
4848 {
4849 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4850
4851 /* Release shader/program objects that may have been initialized in previous
4852 * iterations.
4853 */
4854 deinitIterationSpecificProgramAndShaderObjects();
4855
4856 /* Create program and shader objects */
4857 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
4858 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
4859 m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
4860 m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
4861 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
4862
4863 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
4864
4865 m_po_id = gl.createProgram();
4866 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call(s) failed.");
4867
4868 /* Prepare token replacement strings */
4869 std::stringstream n_samples_sstream;
4870 std::string sampler_declarations_string;
4871 std::string sample_fetch_string;
4872 std::string sample_fetch_fs_string;
4873 std::size_t token_location = std::string::npos;
4874 const char *token_n_samples = "N_SAMPLES";
4875 const char *token_sampler_declarations = "SAMPLER_DECLARATIONS";
4876 const char *token_sample_fetch = "SAMPLE_FETCH";
4877
4878 n_samples_sstream << m_iteration_parent_texture_n_samples;
4879
4880 switch (m_iteration_view_texture_target)
4881 {
4882 case GL_TEXTURE_1D:
4883 {
4884 sampler_declarations_string = "uniform sampler1D texture;";
4885 sample_fetch_string = "vec4 current_sample = textureLod(texture, 0.5, lod);\n";
4886 sample_fetch_fs_string = "vec4 current_sample = textureLod(texture, gs_fs_uv.x, lod);\n";
4887
4888 break;
4889 }
4890
4891 case GL_TEXTURE_1D_ARRAY:
4892 {
4893 sampler_declarations_string = "uniform sampler1DArray texture;\n"
4894 "uniform float z_float;\n";
4895
4896 sample_fetch_string = "vec4 current_sample = textureLod(texture, vec2(0.5, z_float), lod);\n";
4897 sample_fetch_fs_string = "vec4 current_sample = textureLod(texture, vec2(gs_fs_uv.x, z_float), lod);\n";
4898
4899 break;
4900 }
4901
4902 case GL_TEXTURE_2D:
4903 {
4904 sampler_declarations_string = "uniform sampler2D texture;";
4905 sample_fetch_string = "vec4 current_sample = textureLod(texture, vec2(0.5), lod);\n";
4906 sample_fetch_fs_string = "vec4 current_sample = textureLod(texture, gs_fs_uv, lod);\n";
4907
4908 break;
4909 }
4910
4911 case GL_TEXTURE_2D_ARRAY:
4912 {
4913 sampler_declarations_string = "uniform float z_float;\n"
4914 "uniform sampler2DArray texture;";
4915
4916 sample_fetch_string = "vec4 current_sample = textureLod(texture, vec3(vec2(0.5), z_float), lod);\n";
4917 sample_fetch_fs_string = "vec4 current_sample = textureLod(texture, vec3(gs_fs_uv, z_float), lod);\n";
4918
4919 break;
4920 }
4921
4922 case GL_TEXTURE_2D_MULTISAMPLE:
4923 {
4924 sampler_declarations_string = "uniform sampler2DMS texture;";
4925 sample_fetch_string = "ivec2 texture_size = textureSize(texture);\n"
4926 "vec4 current_sample = texelFetch (texture,\n"
4927 " ivec2(texture_size.xy / ivec2(2)),\n"
4928 " n_sample);\n";
4929
4930 sample_fetch_fs_string = "ivec2 texture_size = textureSize(texture);\n"
4931 "vec4 current_sample = texelFetch (texture,\n"
4932 " ivec2(gs_fs_uv * vec2(texture_size)),\n"
4933 " n_sample);\n";
4934
4935 break;
4936 }
4937
4938 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
4939 {
4940 sampler_declarations_string = "uniform sampler2DMSArray texture;"
4941 "uniform int z_int;\n";
4942
4943 sample_fetch_string = "ivec3 texture_size = textureSize(texture);\n"
4944 "vec4 current_sample = texelFetch (texture,\n"
4945 " ivec3(texture_size.xy / ivec2(2), z_int),\n"
4946 " n_sample);\n";
4947
4948 sample_fetch_fs_string =
4949 "ivec3 texture_size = textureSize(texture);\n"
4950 "vec4 current_sample = texelFetch (texture,\n"
4951 " ivec3(ivec2(gs_fs_uv * vec2(texture_size).xy), z_int),\n"
4952 " n_sample);\n";
4953
4954 break;
4955 }
4956
4957 case GL_TEXTURE_3D:
4958 {
4959 sampler_declarations_string = "uniform sampler3D texture;"
4960 "uniform float z_float;";
4961
4962 sample_fetch_string = "vec4 current_sample = textureLod(texture, vec3(vec2(0.5), z_float), lod);\n";
4963 sample_fetch_fs_string = "vec4 current_sample = textureLod(texture, vec3(gs_fs_uv, z_float), lod);\n";
4964
4965 break;
4966 }
4967
4968 case GL_TEXTURE_CUBE_MAP:
4969 {
4970 sampler_declarations_string = "uniform samplerCube texture;\n"
4971 "uniform int n_face;";
4972
4973 sample_fetch_string = "vec4 current_sample;\n"
4974 "\n"
4975 "switch (n_face)\n"
4976 "{\n"
4977 // GL_TEXTURE_CUBE_MAP_POSITIVE_X
4978 " case 0: current_sample = textureLod(texture, vec3( 1, 0, 0), lod); break;\n"
4979 // GL_TEXTURE_CUBE_MAP_NEGATIVE_X
4980 " case 1: current_sample = textureLod(texture, vec3(-1, 0, 0), lod); break;\n"
4981 // GL_TEXTURE_CUBE_MAP_POSITIVE_Y
4982 " case 2: current_sample = textureLod(texture, vec3( 0, 1, 0), lod); break;\n"
4983 // GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
4984 " case 3: current_sample = textureLod(texture, vec3( 0, -1, 0), lod); break;\n"
4985 // GL_TEXTURE_CUBE_MAP_POSITIVE_Z
4986 " case 4: current_sample = textureLod(texture, vec3( 0, 0, 1), lod); break;\n"
4987 // GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
4988 " case 5: current_sample = textureLod(texture, vec3( 0, 0, -1), lod); break;\n"
4989 "}\n";
4990
4991 sample_fetch_fs_string =
4992 "vec4 current_sample;\n"
4993 "\n"
4994 "switch (n_face)\n"
4995 "{\n"
4996 // GL_TEXTURE_CUBE_MAP_POSITIVE_X
4997 " case 0: current_sample = textureLod(texture, normalize(vec3( 1, gs_fs_uv.xy)), lod); break;\n"
4998 // GL_TEXTURE_CUBE_MAP_NEGATIVE_X
4999 " case 1: current_sample = textureLod(texture, normalize(vec3(-1, gs_fs_uv.xy)), lod); break;\n"
5000 // GL_TEXTURE_CUBE_MAP_POSITIVE_Y
5001 " case 2: current_sample = textureLod(texture, normalize(vec3( gs_fs_uv.x, 1, gs_fs_uv.y)), lod); "
5002 "break;\n"
5003 // GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
5004 " case 3: current_sample = textureLod(texture, normalize(vec3( gs_fs_uv.x, -1, gs_fs_uv.y)), lod); "
5005 "break;\n"
5006 // GL_TEXTURE_CUBE_MAP_POSITIVE_Z
5007 " case 4: current_sample = textureLod(texture, normalize(vec3( gs_fs_uv.xy, 1)), lod); break;\n"
5008 // GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
5009 " case 5: current_sample = textureLod(texture, normalize(vec3( gs_fs_uv.xy, -1)), lod); break;\n"
5010 "}\n";
5011 break;
5012 }
5013
5014 case GL_TEXTURE_CUBE_MAP_ARRAY:
5015 {
5016 sampler_declarations_string = "uniform samplerCubeArray texture;\n"
5017 "uniform int n_face;\n"
5018 "uniform float z_float;\n";
5019
5020 sample_fetch_string =
5021 "vec4 current_sample;\n"
5022 "\n"
5023 "switch (n_face)\n"
5024 "{\n"
5025 // GL_TEXTURE_CUBE_MAP_POSITIVE_X
5026 " case 0: current_sample = textureLod(texture, vec4( 1, 0, 0, z_float), lod); break;\n"
5027 // GL_TEXTURE_CUBE_MAP_NEGATIVE_X
5028 " case 1: current_sample = textureLod(texture, vec4(-1, 0, 0, z_float), lod); break;\n"
5029 // GL_TEXTURE_CUBE_MAP_POSITIVE_Y
5030 " case 2: current_sample = textureLod(texture, vec4( 0, 1, 0, z_float), lod); break;\n"
5031 // GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
5032 " case 3: current_sample = textureLod(texture, vec4( 0, -1, 0, z_float), lod); break;\n"
5033 // GL_TEXTURE_CUBE_MAP_POSITIVE_Z
5034 " case 4: current_sample = textureLod(texture, vec4( 0, 0, 1, z_float), lod); break;\n"
5035 // GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
5036 " case 5: current_sample = textureLod(texture, vec4( 0, 0, -1, z_float), lod); break;\n"
5037 "}\n";
5038
5039 sample_fetch_fs_string = "vec4 current_sample;\n"
5040 "\n"
5041 "switch (n_face)\n"
5042 "{\n"
5043 // GL_TEXTURE_CUBE_MAP_POSITIVE_X
5044 " case 0: current_sample = textureLod(texture, vec4(normalize(vec3( 1, "
5045 "gs_fs_uv.xy)), z_float), lod); break;\n"
5046 // GL_TEXTURE_CUBE_MAP_NEGATIVE_X
5047 " case 1: current_sample = textureLod(texture, vec4(normalize(vec3(-1, "
5048 "gs_fs_uv.xy)), z_float), lod); break;\n"
5049 // GL_TEXTURE_CUBE_MAP_POSITIVE_Y
5050 " case 2: current_sample = textureLod(texture, vec4(normalize(vec3( gs_fs_uv.x, 1, "
5051 " gs_fs_uv.y)), z_float), lod); break;\n"
5052 // GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
5053 " case 3: current_sample = textureLod(texture, vec4(normalize(vec3( gs_fs_uv.x, "
5054 "-1, gs_fs_uv.y)), z_float), lod); break;\n"
5055 // GL_TEXTURE_CUBE_MAP_POSITIVE_Z
5056 " case 4: current_sample = textureLod(texture, vec4(normalize(vec3( gs_fs_uv.xy, "
5057 "1)), z_float), lod); break;\n"
5058 // GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
5059 " case 5: current_sample = textureLod(texture, vec4(normalize(vec3( gs_fs_uv.xy, "
5060 "-1)), z_float), lod); break;\n"
5061 "}\n";
5062
5063 break;
5064 }
5065
5066 case GL_TEXTURE_RECTANGLE:
5067 {
5068 sampler_declarations_string = "uniform sampler2DRect texture;";
5069 sample_fetch_string = "ivec2 texture_size = textureSize(texture);\n"
5070 "vec4 current_sample = texelFetch (texture, texture_size / ivec2(2));\n";
5071
5072 sample_fetch_fs_string =
5073 "ivec2 texture_size = textureSize(texture);\n"
5074 "vec4 current_sample = texelFetch (texture, ivec2(gs_fs_uv.xy * vec2(texture_size)));\n";
5075
5076 break;
5077 }
5078
5079 default:
5080 {
5081 TCU_FAIL("Unrecognized texture target");
5082 }
5083 } /* switch (m_iteration_view_texture_target) */
5084
5085 /* Set vertex shader's body */
5086 const char *vs_body = "#version 400\n"
5087 "\n"
5088 "uniform float lod;\n"
5089 "uniform vec4 reference_colors[N_SAMPLES];\n"
5090 "SAMPLER_DECLARATIONS\n"
5091 "\n"
5092 "out int vs_tc_vs_sampling_result;\n"
5093 "\n"
5094 "void main()\n"
5095 "{\n"
5096 " const float epsilon = 1.0 / 255.0;\n"
5097 "\n"
5098 " vs_tc_vs_sampling_result = 1;\n"
5099 "\n"
5100 " for (int n_sample = 0; n_sample < N_SAMPLES; ++n_sample)\n"
5101 " {\n"
5102 " SAMPLE_FETCH;\n"
5103 "\n"
5104 " if (abs(current_sample.x - reference_colors[n_sample].x) > epsilon ||\n"
5105 " abs(current_sample.y - reference_colors[n_sample].y) > epsilon ||\n"
5106 " abs(current_sample.z - reference_colors[n_sample].z) > epsilon ||\n"
5107 " abs(current_sample.w - reference_colors[n_sample].w) > epsilon)\n"
5108 " {\n"
5109 " vs_tc_vs_sampling_result = int(current_sample.x * 256.0);\n"
5110 "\n"
5111 " break;\n"
5112 " }\n"
5113 " }\n"
5114 "\n"
5115 " gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
5116 "}\n";
5117 std::string vs_string = vs_body;
5118
5119 while ((token_location = vs_string.find(token_n_samples)) != std::string::npos)
5120 {
5121 vs_string.replace(token_location, strlen(token_n_samples), n_samples_sstream.str());
5122 }
5123
5124 while ((token_location = vs_string.find(token_sampler_declarations)) != std::string::npos)
5125 {
5126 vs_string.replace(token_location, strlen(token_sampler_declarations), sampler_declarations_string);
5127 }
5128
5129 while ((token_location = vs_string.find(token_sample_fetch)) != std::string::npos)
5130 {
5131 vs_string.replace(token_location, strlen(token_sample_fetch), sample_fetch_string);
5132 }
5133
5134 /* Set tessellation control shader's body */
5135 const char *tc_body = "#version 400\n"
5136 "\n"
5137 "layout(vertices = 1) out;\n"
5138 "\n"
5139 "uniform float lod;\n"
5140 "uniform vec4 reference_colors[N_SAMPLES];\n"
5141 "SAMPLER_DECLARATIONS\n"
5142 "\n"
5143 "in int vs_tc_vs_sampling_result[];\n"
5144 "out int tc_te_vs_sampling_result[];\n"
5145 "out int tc_te_tc_sampling_result[];\n"
5146 "\n"
5147 "void main()\n"
5148 "{\n"
5149 " const float epsilon = 1.0 / 255.0;\n"
5150 "\n"
5151 " tc_te_vs_sampling_result[gl_InvocationID] = vs_tc_vs_sampling_result[gl_InvocationID];\n"
5152 " tc_te_tc_sampling_result[gl_InvocationID] = 1;\n"
5153 "\n"
5154 " for (int n_sample = 0; n_sample < N_SAMPLES; ++n_sample)\n"
5155 " {\n"
5156 " SAMPLE_FETCH\n"
5157 "\n"
5158 " if (abs(current_sample.x - reference_colors[n_sample].x) > epsilon ||\n"
5159 " abs(current_sample.y - reference_colors[n_sample].y) > epsilon ||\n"
5160 " abs(current_sample.z - reference_colors[n_sample].z) > epsilon ||\n"
5161 " abs(current_sample.w - reference_colors[n_sample].w) > epsilon)\n"
5162 " {\n"
5163 " tc_te_tc_sampling_result[gl_InvocationID] = 0;\n"
5164 "\n"
5165 " break;\n"
5166 " }\n"
5167 " }\n"
5168 "\n"
5169 " gl_TessLevelInner[0] = 1.0;\n"
5170 " gl_TessLevelInner[1] = 1.0;\n"
5171 " gl_TessLevelOuter[0] = 1.0;\n"
5172 " gl_TessLevelOuter[1] = 1.0;\n"
5173 " gl_TessLevelOuter[2] = 1.0;\n"
5174 " gl_TessLevelOuter[3] = 1.0;\n"
5175 "}\n";
5176
5177 std::string tc_string = tc_body;
5178
5179 while ((token_location = tc_string.find(token_n_samples)) != std::string::npos)
5180 {
5181 tc_string.replace(token_location, strlen(token_n_samples), n_samples_sstream.str());
5182 }
5183
5184 while ((token_location = tc_string.find(token_sampler_declarations)) != std::string::npos)
5185 {
5186 tc_string.replace(token_location, strlen(token_sampler_declarations), sampler_declarations_string);
5187 }
5188
5189 while ((token_location = tc_string.find(token_sample_fetch)) != std::string::npos)
5190 {
5191 tc_string.replace(token_location, strlen(token_sample_fetch), sample_fetch_string);
5192 }
5193
5194 /* Set tessellation evaluation shader's body */
5195 const char *te_body = "#version 400\n"
5196 "\n"
5197 "layout(quads) in;\n"
5198 "\n"
5199 "in int tc_te_vs_sampling_result[];\n"
5200 "in int tc_te_tc_sampling_result[];\n"
5201 "out int te_gs_vs_sampling_result;\n"
5202 "out int te_gs_tc_sampling_result;\n"
5203 "out int te_gs_te_sampling_result;\n"
5204 "out vec2 te_gs_uv;\n"
5205 "\n"
5206 "uniform float lod;\n"
5207 "uniform vec4 reference_colors[N_SAMPLES];\n"
5208 "SAMPLER_DECLARATIONS\n"
5209 "\n"
5210 "void main()\n"
5211 "{\n"
5212 " te_gs_vs_sampling_result = tc_te_vs_sampling_result[0];\n"
5213 " te_gs_tc_sampling_result = tc_te_tc_sampling_result[0];\n"
5214 " te_gs_te_sampling_result = 1;\n"
5215 "\n"
5216 /* gl_TessCoord spans from 0 to 1 for XY. To generate a screen-space quad,
5217 * we need to project these components to <-1, 1>. */
5218 " gl_Position.xy = gl_TessCoord.xy * 2.0 - 1.0;\n"
5219 " gl_Position.zw = vec2(0, 1);\n"
5220 " te_gs_uv = vec2(gl_TessCoord.x, 1.0 - gl_TessCoord.y);\n"
5221 "\n"
5222 "\n"
5223 " const float epsilon = 1.0 / 255.0;\n"
5224 "\n"
5225 " for (int n_sample = 0; n_sample < N_SAMPLES; ++n_sample)\n"
5226 " {\n"
5227 " SAMPLE_FETCH\n"
5228 "\n"
5229 " if (abs(current_sample.x - reference_colors[n_sample].x) > epsilon ||\n"
5230 " abs(current_sample.y - reference_colors[n_sample].y) > epsilon ||\n"
5231 " abs(current_sample.z - reference_colors[n_sample].z) > epsilon ||\n"
5232 " abs(current_sample.w - reference_colors[n_sample].w) > epsilon)\n"
5233 " {\n"
5234 " te_gs_te_sampling_result = 0;\n"
5235 "\n"
5236 " break;\n"
5237 " }\n"
5238 " }\n"
5239 "\n"
5240 "}\n";
5241
5242 std::string te_string = te_body;
5243
5244 while ((token_location = te_string.find(token_n_samples)) != std::string::npos)
5245 {
5246 te_string.replace(token_location, strlen(token_n_samples), n_samples_sstream.str());
5247 }
5248
5249 while ((token_location = te_string.find(token_sampler_declarations)) != std::string::npos)
5250 {
5251 te_string.replace(token_location, strlen(token_sampler_declarations), sampler_declarations_string);
5252 }
5253
5254 while ((token_location = te_string.find(token_sample_fetch)) != std::string::npos)
5255 {
5256 te_string.replace(token_location, strlen(token_sample_fetch), sample_fetch_string);
5257 }
5258
5259 /* Set geometry shader's body */
5260 const char *gs_body = "#version 400\n"
5261 "\n"
5262 "layout (triangles) in;\n"
5263 "layout (triangle_strip, max_vertices = 3) out;\n"
5264 "\n"
5265 "in int te_gs_vs_sampling_result[];\n"
5266 "in int te_gs_tc_sampling_result[];\n"
5267 "in int te_gs_te_sampling_result[];\n"
5268 "in vec2 te_gs_uv [];\n"
5269 "out int gs_fs_vs_sampling_result;\n"
5270 "out int gs_fs_tc_sampling_result;\n"
5271 "out int gs_fs_te_sampling_result;\n"
5272 "out int gs_fs_gs_sampling_result;\n"
5273 "out vec2 gs_fs_uv;\n"
5274 "\n"
5275 "uniform float lod;\n"
5276 "uniform vec4 reference_colors[N_SAMPLES];\n"
5277 "SAMPLER_DECLARATIONS\n"
5278 "\n"
5279 "void main()\n"
5280 "{\n"
5281 " const float epsilon = 1.0 / 255.0;\n"
5282 " int gs_sampling_result = 1;\n"
5283 " int tc_sampling_result = te_gs_tc_sampling_result[0] & "
5284 "te_gs_tc_sampling_result[1] & te_gs_tc_sampling_result[2];\n"
5285 " int te_sampling_result = te_gs_te_sampling_result[0] & "
5286 "te_gs_te_sampling_result[1] & te_gs_te_sampling_result[2];\n"
5287 " int vs_sampling_result = te_gs_vs_sampling_result[0] & "
5288 "te_gs_vs_sampling_result[1] & te_gs_vs_sampling_result[2];\n"
5289 "\n"
5290 " for (int n_sample = 0; n_sample < N_SAMPLES; ++n_sample)\n"
5291 " {\n"
5292 " SAMPLE_FETCH;\n"
5293 "\n"
5294 " if (abs(current_sample.x - reference_colors[n_sample].x) > epsilon ||\n"
5295 " abs(current_sample.y - reference_colors[n_sample].y) > epsilon ||\n"
5296 " abs(current_sample.z - reference_colors[n_sample].z) > epsilon ||\n"
5297 " abs(current_sample.w - reference_colors[n_sample].w) > epsilon)\n"
5298 " {\n"
5299 " gs_sampling_result = 0;\n"
5300 "\n"
5301 " break;\n"
5302 " }\n"
5303 " }\n"
5304 "\n"
5305 " gl_Position = gl_in[0].gl_Position;\n"
5306 " gs_fs_uv = te_gs_uv[0];\n"
5307 " gs_fs_gs_sampling_result = gs_sampling_result;\n"
5308 " gs_fs_tc_sampling_result = tc_sampling_result;\n"
5309 " gs_fs_te_sampling_result = te_sampling_result;\n"
5310 " gs_fs_vs_sampling_result = vs_sampling_result;\n"
5311 " EmitVertex();\n"
5312 "\n"
5313 " gl_Position = gl_in[1].gl_Position;\n"
5314 " gs_fs_uv = te_gs_uv[1];\n"
5315 " gs_fs_gs_sampling_result = gs_sampling_result;\n"
5316 " gs_fs_tc_sampling_result = tc_sampling_result;\n"
5317 " gs_fs_te_sampling_result = te_sampling_result;\n"
5318 " gs_fs_vs_sampling_result = vs_sampling_result;\n"
5319 " EmitVertex();\n"
5320 "\n"
5321 " gl_Position = gl_in[2].gl_Position;\n"
5322 " gs_fs_uv = te_gs_uv[2];\n"
5323 " gs_fs_gs_sampling_result = gs_sampling_result;\n"
5324 " gs_fs_tc_sampling_result = tc_sampling_result;\n"
5325 " gs_fs_te_sampling_result = te_sampling_result;\n"
5326 " gs_fs_vs_sampling_result = vs_sampling_result;\n"
5327 " EmitVertex();\n"
5328 " EndPrimitive();\n"
5329 "}\n";
5330
5331 std::string gs_string = gs_body;
5332
5333 while ((token_location = gs_string.find(token_n_samples)) != std::string::npos)
5334 {
5335 gs_string.replace(token_location, strlen(token_n_samples), n_samples_sstream.str());
5336 }
5337
5338 while ((token_location = gs_string.find(token_sampler_declarations)) != std::string::npos)
5339 {
5340 gs_string.replace(token_location, strlen(token_sampler_declarations), sampler_declarations_string);
5341 }
5342
5343 while ((token_location = gs_string.find(token_sample_fetch)) != std::string::npos)
5344 {
5345 gs_string.replace(token_location, strlen(token_sample_fetch), sample_fetch_string);
5346 }
5347
5348 /* Set fragment shader's body */
5349 const char *fs_body = "#version 400\n"
5350 "\n"
5351 "in vec2 gs_fs_uv;\n"
5352 "\n"
5353 "uniform float lod;\n"
5354 "uniform vec4 reference_colors[N_SAMPLES];\n"
5355 "SAMPLER_DECLARATIONS\n"
5356 "\n"
5357 "out vec4 result;\n"
5358 "\n"
5359 "void main()\n"
5360 "{\n"
5361 " const float epsilon = 1.0 / 255.0;\n"
5362 "\n"
5363 " result = vec4(1.0);\n"
5364 "\n"
5365 " for (int n_sample = 0; n_sample < N_SAMPLES; ++n_sample)\n"
5366 " {\n"
5367 " SAMPLE_FETCH\n"
5368 "\n"
5369 " if (abs(current_sample.x - reference_colors[n_sample].x) > epsilon ||\n"
5370 " abs(current_sample.y - reference_colors[n_sample].y) > epsilon ||\n"
5371 " abs(current_sample.z - reference_colors[n_sample].z) > epsilon ||\n"
5372 " abs(current_sample.w - reference_colors[n_sample].w) > epsilon)\n"
5373 " {\n"
5374 " result = vec4(0.0);\n"
5375 "\n"
5376 " break;\n"
5377 " }\n"
5378 " }\n"
5379 "}\n";
5380
5381 std::string fs_string = fs_body;
5382
5383 while ((token_location = fs_string.find(token_n_samples)) != std::string::npos)
5384 {
5385 fs_string.replace(token_location, strlen(token_n_samples), n_samples_sstream.str());
5386 }
5387
5388 while ((token_location = fs_string.find(token_sampler_declarations)) != std::string::npos)
5389 {
5390 fs_string.replace(token_location, strlen(token_sampler_declarations), sampler_declarations_string);
5391 }
5392
5393 while ((token_location = fs_string.find(token_sample_fetch)) != std::string::npos)
5394 {
5395 fs_string.replace(token_location, strlen(token_sample_fetch), sample_fetch_fs_string);
5396 }
5397
5398 /* Configure shader bodies */
5399 const char *fs_body_raw_ptr = fs_string.c_str();
5400 const char *gs_body_raw_ptr = gs_string.c_str();
5401 const char *tc_body_raw_ptr = tc_string.c_str();
5402 const char *te_body_raw_ptr = te_string.c_str();
5403 const char *vs_body_raw_ptr = vs_string.c_str();
5404
5405 gl.shaderSource(m_fs_id, 1 /* count */, &fs_body_raw_ptr, NULL /* length */);
5406 gl.shaderSource(m_gs_id, 1 /* count */, &gs_body_raw_ptr, NULL /* length */);
5407 gl.shaderSource(m_tc_id, 1 /* count */, &tc_body_raw_ptr, NULL /* length */);
5408 gl.shaderSource(m_te_id, 1 /* count */, &te_body_raw_ptr, NULL /* length */);
5409 gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, NULL /* length */);
5410 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call(s) failed.");
5411
5412 /* Compile the shaders */
5413 const glw::GLuint so_ids[] = {m_fs_id, m_gs_id, m_tc_id, m_te_id, m_vs_id};
5414 const unsigned int n_so_ids = sizeof(so_ids) / sizeof(so_ids[0]);
5415
5416 const glw::GLchar *shader_sources[] = {fs_body_raw_ptr, gs_body_raw_ptr, tc_body_raw_ptr, te_body_raw_ptr,
5417 vs_body_raw_ptr};
5418
5419 for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id)
5420 {
5421 glw::GLint compile_status = GL_FALSE;
5422 glw::GLint so_id = so_ids[n_so_id];
5423
5424 gl.compileShader(so_id);
5425 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
5426
5427 gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
5428 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
5429
5430 if (compile_status != GL_TRUE)
5431 {
5432 char temp[1024];
5433
5434 gl.getShaderInfoLog(so_id, 1024, NULL, temp);
5435
5436 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader compilation error log:\n"
5437 << temp << "\nShader source:\n"
5438 << shader_sources[n_so_id] << tcu::TestLog::EndMessage;
5439
5440 TCU_FAIL("Shader compilation failed");
5441 }
5442
5443 /* Attach the shaders to the program object */
5444 gl.attachShader(m_po_id, so_id);
5445 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed");
5446 } /* for (all shader objects) */
5447
5448 /* Set up XFB */
5449 const char *varying_names[] = {"gs_fs_vs_sampling_result", "gs_fs_tc_sampling_result", "gs_fs_te_sampling_result",
5450 "gs_fs_gs_sampling_result"};
5451 const unsigned int n_varying_names = sizeof(varying_names) / sizeof(varying_names[0]);
5452
5453 gl.transformFeedbackVaryings(m_po_id, n_varying_names, varying_names, GL_INTERLEAVED_ATTRIBS);
5454 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
5455
5456 /* Link the program object */
5457 glw::GLint link_status = GL_FALSE;
5458
5459 gl.linkProgram(m_po_id);
5460 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
5461
5462 gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
5463 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
5464
5465 if (link_status != GL_TRUE)
5466 {
5467 TCU_FAIL("Program linking failed.");
5468 }
5469
5470 /* Retrieve uniform locations. Depending on the iteration, a number of those will be
5471 * inactive.
5472 */
5473 m_po_lod_location = gl.getUniformLocation(m_po_id, "lod");
5474 m_po_n_face_location = gl.getUniformLocation(m_po_id, "n_face");
5475 m_po_reference_colors_location = gl.getUniformLocation(m_po_id, "reference_colors");
5476 m_po_texture_location = gl.getUniformLocation(m_po_id, "texture");
5477 m_po_z_float_location = gl.getUniformLocation(m_po_id, "z_float");
5478 m_po_z_int_location = gl.getUniformLocation(m_po_id, "z_int");
5479
5480 if (m_po_reference_colors_location == -1)
5481 {
5482 TCU_FAIL("reference_colors is considered an inactive uniform which is invalid.");
5483 }
5484 }
5485
5486 /** Initializes contents of a texture, from which the view texture will be created. **/
initParentTextureContents()5487 void TextureViewTestViewSampling::initParentTextureContents()
5488 {
5489 static const glw::GLenum cm_texture_targets[] = {
5490 /* NOTE: This order must match the order used for sampling CM/CMA texture targets. */
5491 GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
5492 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z};
5493 static const unsigned int n_cm_texture_targets = sizeof(cm_texture_targets) / sizeof(cm_texture_targets[0]);
5494 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
5495
5496 /* Bind the parent texture */
5497 gl.bindTexture(m_iteration_parent_texture_target, m_to_id);
5498 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
5499
5500 /* If we're dealing with a single-sampled texture target, then we can clear the
5501 * contents of each layer/face/slice using FBO. This will unfortunately not work
5502 * for arrayed textures, layers or layer-faces of which cannot be attached to a draw
5503 * framebuffer.
5504 * If we need to update contents of a multisampled, potentially arrayed texture,
5505 * we'll need to use the filler program.
5506 **/
5507 bool is_arrayed_texture_target = (m_iteration_parent_texture_target == GL_TEXTURE_1D_ARRAY ||
5508 m_iteration_parent_texture_target == GL_TEXTURE_2D_ARRAY ||
5509 m_iteration_parent_texture_target == GL_TEXTURE_CUBE_MAP_ARRAY);
5510 bool is_multisampled_texture_target = (m_iteration_parent_texture_target == GL_TEXTURE_2D_MULTISAMPLE ||
5511 m_iteration_parent_texture_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY);
5512
5513 if (!is_arrayed_texture_target && !is_multisampled_texture_target)
5514 {
5515 /* Good, no need to work with samples! */
5516 DE_ASSERT(m_iteration_parent_texture_depth >= 1);
5517 DE_ASSERT(m_iteration_parent_texture_n_levels >= 1);
5518
5519 /* Cube-map texture target cannot be directly used for a glFramebufferTexture2D() call. Instead,
5520 * we need to split it into 6 cube-map texture targets. */
5521 unsigned int n_texture_targets = 1;
5522 glw::GLenum texture_targets[n_cm_texture_targets] = {
5523 m_iteration_parent_texture_target, GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE,
5524 };
5525
5526 if (m_iteration_parent_texture_target == GL_TEXTURE_CUBE_MAP)
5527 {
5528 DE_STATIC_ASSERT(sizeof(texture_targets) == sizeof(cm_texture_targets));
5529 memcpy(texture_targets, cm_texture_targets, sizeof(cm_texture_targets));
5530
5531 n_texture_targets = n_cm_texture_targets;
5532 }
5533
5534 resetReferenceColorStorage(m_iteration_parent_texture_depth, /* n_layers */
5535 n_texture_targets, /* n_faces */
5536 m_iteration_parent_texture_n_levels, /* n_mipmaps */
5537 1); /* n_samples */
5538
5539 /* Iterate through all texture targets we need to update */
5540 for (unsigned int n_texture_target = 0; n_texture_target < n_texture_targets; ++n_texture_target)
5541 {
5542 const glw::GLenum texture_target = texture_targets[n_texture_target];
5543
5544 /* Iterate through all layers of the texture. */
5545 for (unsigned int n_layer = 0; n_layer < m_iteration_parent_texture_depth; ++n_layer)
5546 {
5547 /* ..and mip-maps, too. */
5548 const unsigned int n_mipmaps_for_layer = (texture_target == GL_TEXTURE_3D) ?
5549 (m_iteration_parent_texture_n_levels - n_layer) :
5550 (m_iteration_parent_texture_n_levels);
5551
5552 for (unsigned int n_mipmap = 0; n_mipmap < n_mipmaps_for_layer; ++n_mipmap)
5553 {
5554 /* Use appropriate glFramebufferTexture*() API, depending on the texture target of the
5555 * parent texture.
5556 */
5557 switch (texture_target)
5558 {
5559 case GL_TEXTURE_1D:
5560 {
5561 gl.framebufferTexture1D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_1D, m_to_id,
5562 n_mipmap);
5563
5564 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture1D() call failed.");
5565 break;
5566 }
5567
5568 case GL_TEXTURE_2D:
5569 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
5570 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
5571 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
5572 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
5573 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
5574 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
5575 case GL_TEXTURE_RECTANGLE:
5576 {
5577 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture_target, m_to_id,
5578 n_mipmap);
5579
5580 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
5581 break;
5582 }
5583
5584 case GL_TEXTURE_3D:
5585 {
5586 gl.framebufferTexture3D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_3D, m_to_id,
5587 n_mipmap, n_layer);
5588
5589 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture3D() call failed.");
5590 break;
5591 }
5592
5593 default:
5594 {
5595 TCU_FAIL("Unrecognized texture target");
5596 }
5597 } /* switch (m_iteration_parent_texture_target) */
5598
5599 /* Each layer/mipmap needs to be assigned an unique vec4. */
5600 tcu::Vec4 reference_color = getRandomReferenceColor();
5601
5602 setReferenceColor(n_layer, n_texture_target, /* n_face */
5603 n_mipmap, 0, /* n_sample */
5604 reference_color);
5605
5606 /* We should be OK to clear the mip-map at this point */
5607 gl.clearColor(reference_color.x(), reference_color.y(), reference_color.z(), reference_color.w());
5608 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor() call failed.");
5609
5610 gl.clear(GL_COLOR_BUFFER_BIT);
5611 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed.");
5612 } /* for (all mip-maps) */
5613 } /* for (all layers) */
5614 } /* for (all texture targets) */
5615 } /* if (!is_arrayed_texture_target && !is_multisampled_texture_target) */
5616 else
5617 {
5618 /* We need to handle an either multisampled or arrayed texture target or
5619 * a combination of the two.
5620 */
5621 DE_ASSERT(m_iteration_parent_texture_target == GL_TEXTURE_1D_ARRAY ||
5622 m_iteration_parent_texture_target == GL_TEXTURE_2D_ARRAY ||
5623 m_iteration_parent_texture_target == GL_TEXTURE_2D_MULTISAMPLE ||
5624 m_iteration_parent_texture_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY ||
5625 m_iteration_parent_texture_target == GL_TEXTURE_CUBE_MAP_ARRAY);
5626
5627 DE_ASSERT(m_iteration_parent_texture_depth >= 1);
5628 DE_ASSERT(m_iteration_parent_texture_n_levels >= 1);
5629
5630 const unsigned int n_faces =
5631 (m_iteration_parent_texture_target == GL_TEXTURE_CUBE_MAP_ARRAY) ? 6 /* faces */ : 1;
5632
5633 resetReferenceColorStorage(m_iteration_parent_texture_depth / n_faces, /* n_layers */
5634 n_faces, m_iteration_parent_texture_n_levels, /* n_mipmaps */
5635 m_max_color_texture_samples_gl_value); /* n_samples */
5636
5637 /* Set up storage for reference colors the fragment shader should use
5638 * when rendering to multisampled texture target */
5639 float *reference_colors = new float[4 /* rgba */ * m_max_color_texture_samples_gl_value];
5640
5641 /* Activate the filler program */
5642 gl.useProgram(m_per_sample_filler_po_id);
5643 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
5644
5645 /* Iterate through all layers of the texture. */
5646 for (unsigned int n_layer = 0; n_layer < m_iteration_parent_texture_depth / n_faces; ++n_layer)
5647 {
5648 /* ..faces.. */
5649 for (unsigned int n_face = 0; n_face < n_faces; ++n_face)
5650 {
5651 /* ..and mip-maps, too. */
5652 for (unsigned int n_mipmap = 0; n_mipmap < m_iteration_parent_texture_n_levels; ++n_mipmap)
5653 {
5654 /* For all texture targets considered excl. GL_TEXTURE_2D_MULTISAMPLE, we need
5655 * to use glFramebufferTextur() to bind all layers to the color atatchment. For
5656 * 2DMS textures, we can use plain glFramebufferTexture2D().
5657 */
5658 if (m_iteration_parent_texture_target != GL_TEXTURE_2D_MULTISAMPLE)
5659 {
5660 gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_to_id, n_mipmap);
5661
5662 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTextureLayer() call failed.");
5663 }
5664 else
5665 {
5666 /* Quick check */
5667 DE_ASSERT(m_iteration_parent_texture_depth == 1);
5668
5669 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
5670 m_iteration_parent_texture_target, m_to_id, n_mipmap);
5671
5672 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
5673 }
5674
5675 /* Generate reference colors for all samples */
5676 const unsigned int n_samples =
5677 (is_multisampled_texture_target) ? m_max_color_texture_samples_gl_value : 1;
5678
5679 for (unsigned int n_sample = 0; n_sample < n_samples; ++n_sample)
5680 {
5681 tcu::Vec4 reference_color = getRandomReferenceColor();
5682
5683 reference_colors[4 /* rgba */ * n_sample + 0] = reference_color.x();
5684 reference_colors[4 /* rgba */ * n_sample + 1] = reference_color.y();
5685 reference_colors[4 /* rgba */ * n_sample + 2] = reference_color.z();
5686 reference_colors[4 /* rgba */ * n_sample + 3] = reference_color.w();
5687
5688 setReferenceColor(n_layer, n_face, n_mipmap, n_sample, reference_color);
5689 } /* for (all samples) */
5690
5691 /* Upload the reference sample colors */
5692 gl.uniform4fv(m_per_sample_filler_po_reference_colors_location, n_samples, reference_colors);
5693 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4fv() call failed.");
5694
5695 /* Update the layer ID the program should render to */
5696 const unsigned int layer_id = n_layer * n_faces + n_face;
5697
5698 gl.uniform1i(m_per_sample_filler_po_layer_id_location, layer_id);
5699 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i() call failed.");
5700
5701 /* Draw the full-screen quad. Geometry shader will draw the quad for us,
5702 * so all we need to do is to feed the rendering pipeline with a single
5703 * point.
5704 */
5705 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
5706 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
5707 } /* for (all mip-maps) */
5708 } /* for (all faces) */
5709 } /* for (all layers) */
5710
5711 delete[] reference_colors;
5712 }
5713 }
5714
5715 /** Initializes the 'per sample filler' program object, used to fill a multi-sample texture
5716 * with colors varying on a per-sample basis.
5717 */
initPerSampleFillerProgramObject()5718 void TextureViewTestViewSampling::initPerSampleFillerProgramObject()
5719 {
5720 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
5721
5722 /* Quick checks: GL_MAX_COLOR_TEXTURE_SAMPLES is not 0 */
5723 DE_ASSERT(m_max_color_texture_samples_gl_value != 0);
5724
5725 /* Generate program and shader objects */
5726 m_per_sample_filler_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
5727 m_per_sample_filler_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
5728 m_per_sample_filler_vs_id = gl.createShader(GL_VERTEX_SHADER);
5729 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
5730
5731 m_per_sample_filler_po_id = gl.createProgram();
5732 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
5733
5734 /* Configure fragment shader's body */
5735 static const char *fs_body = "#version 400\n"
5736 "\n"
5737 "uniform vec4 reference_colors[N_MAX_SAMPLES];\n"
5738 "\n"
5739 "out vec4 result;\n"
5740 "\n"
5741 "void main()\n"
5742 "{\n"
5743 " result = reference_colors[gl_SampleID];\n"
5744 "}\n";
5745 std::string fs_body_string = fs_body;
5746 const char *fs_body_string_raw_ptr = DE_NULL;
5747 std::stringstream n_max_samples_sstream;
5748 const char *n_max_samples_token = "N_MAX_SAMPLES";
5749 std::size_t token_location = std::string::npos;
5750
5751 n_max_samples_sstream << m_max_color_texture_samples_gl_value;
5752
5753 while ((token_location = fs_body_string.find(n_max_samples_token)) != std::string::npos)
5754 {
5755 fs_body_string.replace(token_location, strlen(n_max_samples_token), n_max_samples_sstream.str());
5756 }
5757
5758 fs_body_string_raw_ptr = fs_body_string.c_str();
5759
5760 gl.shaderSource(m_per_sample_filler_fs_id, 1 /* count */, &fs_body_string_raw_ptr, DE_NULL /* length */);
5761 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
5762
5763 /* Configure geometry shader's body */
5764 static const char *gs_body = "#version 400\n"
5765 "\n"
5766 "layout(points) in;\n"
5767 "layout(triangle_strip, max_vertices = 4) out;\n"
5768 "\n"
5769 "uniform int layer_id;\n"
5770 "\n"
5771 "void main()\n"
5772 "{\n"
5773 " gl_Layer = layer_id;\n"
5774 " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
5775 " EmitVertex();\n"
5776 "\n"
5777 " gl_Layer = layer_id;\n"
5778 " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
5779 " EmitVertex();\n"
5780 "\n"
5781 " gl_Layer = layer_id;\n"
5782 " gl_Position = vec4( 1.0, -1.0, 0.0, 1.0);\n"
5783 " EmitVertex();\n"
5784 "\n"
5785 " gl_Layer = layer_id;\n"
5786 " gl_Position = vec4( 1.0, 1.0, 0.0, 1.0);\n"
5787 " EmitVertex();\n"
5788 "\n"
5789 " EndPrimitive();\n"
5790 "\n"
5791 "}\n";
5792
5793 gl.shaderSource(m_per_sample_filler_gs_id, 1 /* count */, &gs_body, DE_NULL /* length */);
5794 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
5795
5796 /* Configure vertex shader */
5797 static const char *vs_body = "#version 400\n"
5798 "\n"
5799 "void main()\n"
5800 "{\n"
5801 " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
5802 "}\n";
5803
5804 gl.shaderSource(m_per_sample_filler_vs_id, 1 /* count */, &vs_body, DE_NULL /* length */);
5805 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
5806
5807 /* Attach the shaders to the program object */
5808 gl.attachShader(m_per_sample_filler_po_id, m_per_sample_filler_fs_id);
5809 gl.attachShader(m_per_sample_filler_po_id, m_per_sample_filler_gs_id);
5810 gl.attachShader(m_per_sample_filler_po_id, m_per_sample_filler_vs_id);
5811 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed.");
5812
5813 /* Compile the shaders */
5814 const glw::GLuint so_ids[] = {m_per_sample_filler_fs_id, m_per_sample_filler_gs_id, m_per_sample_filler_vs_id};
5815 const unsigned int n_so_ids = sizeof(so_ids) / sizeof(so_ids[0]);
5816
5817 for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id)
5818 {
5819 glw::GLint compile_status = GL_FALSE;
5820 glw::GLuint so_id = so_ids[n_so_id];
5821
5822 gl.compileShader(so_id);
5823 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
5824
5825 gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
5826 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiV() call failed.");
5827
5828 if (compile_status != GL_TRUE)
5829 {
5830 TCU_FAIL("Shader compilation failed.");
5831 }
5832 } /* for (all shader objects) */
5833
5834 /* Link the program object */
5835 glw::GLint link_status = GL_FALSE;
5836
5837 gl.linkProgram(m_per_sample_filler_po_id);
5838 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
5839
5840 gl.getProgramiv(m_per_sample_filler_po_id, GL_LINK_STATUS, &link_status);
5841 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
5842
5843 if (link_status != GL_TRUE)
5844 {
5845 TCU_FAIL("Program linking failed.");
5846 }
5847
5848 /* Retrieve uniform locations */
5849 m_per_sample_filler_po_layer_id_location = gl.getUniformLocation(m_per_sample_filler_po_id, "layer_id");
5850 m_per_sample_filler_po_reference_colors_location =
5851 gl.getUniformLocation(m_per_sample_filler_po_id, "reference_colors[0]");
5852
5853 if (m_per_sample_filler_po_layer_id_location == -1)
5854 {
5855 TCU_FAIL("layer_id uniform is considered inactive which is invalid");
5856 }
5857
5858 if (m_per_sample_filler_po_reference_colors_location == -1)
5859 {
5860 TCU_FAIL("reference_colors uniform is considered inactive which is invalid");
5861 }
5862 }
5863
5864 /** Initializes GL objects needed to run the test (excluding iteration-specific objects) */
initTest()5865 void TextureViewTestViewSampling::initTest()
5866 {
5867 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
5868
5869 /* Generate and configure BO storage to hold result XFB data of a single
5870 * draw call.
5871 *
5872 * Each draw call outputs 6 vertices. For each vertex, 4 ints will be XFBed out. */
5873 gl.genBuffers(1, &m_bo_id);
5874 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
5875
5876 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id);
5877 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
5878
5879 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 6 /* draw calls */ * (4 * sizeof(int)), /* as per comment */
5880 DE_NULL, GL_STATIC_DRAW);
5881 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
5882
5883 /* Generate a FBO and bind it to both binding targets */
5884 gl.genFramebuffers(1, &m_fbo_id);
5885 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
5886
5887 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
5888 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed.");
5889
5890 /* Generate and bind a VAO */
5891 gl.genVertexArrays(1, &m_vao_id);
5892 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
5893
5894 gl.bindVertexArray(m_vao_id);
5895 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
5896
5897 /* Generate and configure a texture object we will use to verify view sampling works correctly
5898 * from within a fragment shader.
5899 */
5900 gl.genTextures(1, &m_result_to_id);
5901 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed.");
5902
5903 gl.bindTexture(GL_TEXTURE_2D, m_result_to_id);
5904 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
5905
5906 gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, m_reference_texture_width, m_reference_texture_height);
5907 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
5908
5909 /* Determine implementation-specific GL_MAX_COLOR_TEXTURE_SAMPLES value */
5910 gl.getIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &m_max_color_texture_samples_gl_value);
5911 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed for GL_MAX_COLOR_TEXTURE_SAMPLES pname.");
5912
5913 /* Modify pixel storage settings so that we don't rely on the default aligment setting. */
5914 gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
5915 gl.pixelStorei(GL_UNPACK_ALIGNMENT, 1);
5916 GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call(s) failed.");
5917
5918 /* Modify GL_PATCH_VERTICES setting so that a single patch consists of only a single vertex
5919 * (instead of the default 3) */
5920 gl.patchParameteri(GL_PATCH_VERTICES, 1);
5921 GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteri() call failed.");
5922 }
5923
5924 /** Initializes and sets up a texture object storage, but does not fill it
5925 * with actual content. Implements separate code paths for handling parent
5926 * & view textures.
5927 *
5928 * @param is_view_texture true if a view texture should be initialized,
5929 * false if te caller needs a parent texture. Note
5930 * that a parent texture must be initialized prior
5931 * to configuring a view texture.
5932 * @param texture_target Texture target to use for the parent texture.
5933 * @param view_texture_target Texture target to use for the view texture.
5934 **/
initTextureObject(bool is_view_texture,glw::GLenum texture_target,glw::GLenum view_texture_target)5935 void TextureViewTestViewSampling::initTextureObject(bool is_view_texture, glw::GLenum texture_target,
5936 glw::GLenum view_texture_target)
5937 {
5938 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
5939 unsigned int texture_depth = 0;
5940 glw::GLuint *to_id_ptr = (is_view_texture) ? &m_view_to_id : &m_to_id;
5941
5942 /* Quick check: make sure GL_TEXTURE_BUFFER texture target is not requested. This
5943 * would be against the test specification.
5944 **/
5945 DE_ASSERT(texture_target != GL_TEXTURE_BUFFER);
5946 DE_ASSERT(view_texture_target != GL_TEXTURE_BUFFER);
5947
5948 /* If we're going to be creating a cube-map or cube-map array texture view in this iteration,
5949 * make sure the parent or view texture's depth is valid */
5950 if (view_texture_target == GL_TEXTURE_CUBE_MAP_ARRAY)
5951 {
5952 texture_depth = 13; /* 1 + 2 * (6 faces) */
5953 }
5954 else if (view_texture_target == GL_TEXTURE_CUBE_MAP)
5955 {
5956 texture_depth = 7; /* 1 + (6 faces) */
5957 }
5958 else
5959 {
5960 texture_depth = m_reference_texture_depth;
5961 }
5962
5963 if (texture_target == GL_TEXTURE_CUBE_MAP_ARRAY)
5964 {
5965 texture_depth = 6 /* faces */ * 3;
5966 }
5967
5968 /* Release the texture object, as we're using immutable texture objects and would
5969 * prefer the resources not to leak.
5970 */
5971 if (*to_id_ptr != 0)
5972 {
5973 gl.deleteTextures(1, to_id_ptr);
5974
5975 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures() call failed.");
5976 }
5977
5978 /* Generate a new texture object */
5979 gl.genTextures(1, to_id_ptr);
5980 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed.");
5981
5982 if (is_view_texture)
5983 {
5984 /* Determine values of arguments we'll pass to glTextureView() call */
5985 unsigned int minlayer = 0;
5986 unsigned int minlevel = 0;
5987 unsigned int numlayers = 0;
5988 unsigned int numlevels = 2;
5989
5990 const bool is_texture_arrayed_texture_target =
5991 (texture_target == GL_TEXTURE_1D_ARRAY || texture_target == GL_TEXTURE_2D_ARRAY ||
5992 texture_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY || texture_target == GL_TEXTURE_CUBE_MAP_ARRAY);
5993 const bool is_texture_cube_map_texture_target = (texture_target == GL_TEXTURE_CUBE_MAP);
5994 const bool is_texture_multisample_texture_target =
5995 (texture_target == GL_TEXTURE_2D_MULTISAMPLE || texture_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY);
5996 const bool is_texture_rectangle_texture_target = (texture_target == GL_TEXTURE_RECTANGLE);
5997 const bool is_view_arrayed_texture_target =
5998 (view_texture_target == GL_TEXTURE_1D_ARRAY || view_texture_target == GL_TEXTURE_2D_ARRAY ||
5999 view_texture_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY ||
6000 view_texture_target == GL_TEXTURE_CUBE_MAP_ARRAY);
6001 const bool is_view_cube_map_texture_target = (view_texture_target == GL_TEXTURE_CUBE_MAP);
6002 const bool is_view_cube_map_array_texture_target = (view_texture_target == GL_TEXTURE_CUBE_MAP_ARRAY);
6003
6004 if (is_texture_multisample_texture_target || is_texture_rectangle_texture_target)
6005 {
6006 minlevel = 0;
6007 numlevels = 1;
6008 }
6009 else
6010 {
6011 minlevel = 1;
6012 }
6013
6014 if ((true == is_texture_arrayed_texture_target) ||
6015 ((false == is_texture_cube_map_texture_target) && (true == is_view_cube_map_texture_target)) ||
6016 ((false == is_texture_cube_map_texture_target) && (true == is_view_cube_map_array_texture_target)))
6017 {
6018 minlayer = 1;
6019 }
6020 else
6021 {
6022 minlayer = 0;
6023 }
6024
6025 if (!is_texture_cube_map_texture_target && is_view_cube_map_array_texture_target)
6026 {
6027 numlayers = 12;
6028 }
6029 else if (is_view_cube_map_texture_target || is_view_cube_map_array_texture_target)
6030 {
6031 numlayers = 6;
6032 }
6033 else if (is_view_arrayed_texture_target)
6034 {
6035 if (is_texture_arrayed_texture_target || is_texture_cube_map_texture_target)
6036 {
6037 numlayers = 2;
6038 }
6039 else
6040 {
6041 numlayers = 1;
6042 }
6043 }
6044 else
6045 {
6046 numlayers = 1;
6047 }
6048
6049 /* Set up view texture */
6050 gl.textureView(*to_id_ptr, view_texture_target, m_to_id, GL_RGBA8, minlevel, numlevels, minlayer, numlayers);
6051
6052 GLU_EXPECT_NO_ERROR(gl.getError(), "glTextureView() call failed.");
6053
6054 /* Store the argument values */
6055 m_iteration_view_texture_minlayer = minlayer;
6056 m_iteration_view_texture_minlevel = minlevel;
6057 m_iteration_view_texture_numlayers = numlayers;
6058 m_iteration_view_texture_numlevels = numlevels;
6059 m_iteration_view_texture_target = view_texture_target;
6060
6061 m_testCtx.getLog() << tcu::TestLog::Message << "Created a view for texture target "
6062 << "[" << TextureViewUtilities::getTextureTargetString(view_texture_target) << "] "
6063 << "from a parent texture target "
6064 << "[" << TextureViewUtilities::getTextureTargetString(texture_target) << "] "
6065 << "using arguments: "
6066 << "minlayer:[" << minlayer << "] "
6067 << "minlevel:[" << minlevel << "] "
6068 << "numlayers:[" << numlayers << "] "
6069 << "numlevels:[" << numlevels << "]." << tcu::TestLog::EndMessage;
6070
6071 gl.bindTexture(view_texture_target, *to_id_ptr);
6072 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
6073 } /* if (is_view_texture) */
6074 else
6075 {
6076 /* Reset iteration-specific view settings */
6077 m_iteration_parent_texture_depth = 1;
6078 m_iteration_parent_texture_height = 1;
6079 m_iteration_parent_texture_n_levels = 1;
6080 m_iteration_parent_texture_n_samples = 1;
6081 m_iteration_parent_texture_width = 1;
6082
6083 /* Initialize storage for the newly created texture object */
6084 gl.bindTexture(texture_target, *to_id_ptr);
6085 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
6086
6087 /* Use max conformant sample count for multisample texture targets */
6088 if (texture_target == GL_TEXTURE_2D_MULTISAMPLE || texture_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)
6089 {
6090 m_max_color_texture_samples_gl_value = getMaxConformantSampleCount(texture_target, GL_RGBA8);
6091 }
6092 else
6093 {
6094 /* Use GL_MAX_COLOR_TEXTURE_SAMPLES value for other targets */
6095 gl.getIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &m_max_color_texture_samples_gl_value);
6096 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed for GL_MAX_COLOR_TEXTURE_SAMPLES pname.");
6097 }
6098
6099 switch (texture_target)
6100 {
6101 case GL_TEXTURE_1D:
6102 {
6103 gl.texStorage1D(texture_target, m_reference_texture_n_mipmaps, GL_RGBA8, m_reference_texture_width);
6104
6105 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage1D() call failed.");
6106
6107 m_iteration_parent_texture_n_levels = m_reference_texture_n_mipmaps;
6108 m_iteration_parent_texture_width = m_reference_texture_width;
6109
6110 m_testCtx.getLog() << tcu::TestLog::Message
6111 << "Created an immutable parent texture object for texture target "
6112 << "[" << TextureViewUtilities::getTextureTargetString(texture_target) << "] "
6113 << "of "
6114 << "levels:[" << m_reference_texture_n_mipmaps << "] "
6115 << "width:[" << m_reference_texture_width << "]." << tcu::TestLog::EndMessage;
6116 break;
6117 }
6118
6119 case GL_TEXTURE_1D_ARRAY:
6120 {
6121 gl.texStorage2D(texture_target, m_reference_texture_n_mipmaps, GL_RGBA8, m_reference_texture_width,
6122 texture_depth);
6123
6124 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
6125
6126 m_iteration_parent_texture_depth = texture_depth;
6127 m_iteration_parent_texture_n_levels = m_reference_texture_n_mipmaps;
6128 m_iteration_parent_texture_width = m_reference_texture_width;
6129
6130 m_testCtx.getLog() << tcu::TestLog::Message
6131 << "Created an immutable parent texture object for texture target "
6132 << "[" << TextureViewUtilities::getTextureTargetString(texture_target) << "] "
6133 << "of "
6134 << "depth:[" << texture_depth << "] "
6135 << "levels:[" << m_reference_texture_n_mipmaps << "] "
6136 << "width:[" << m_reference_texture_width << "]." << tcu::TestLog::EndMessage;
6137
6138 break;
6139 }
6140
6141 case GL_TEXTURE_CUBE_MAP:
6142 case GL_TEXTURE_2D:
6143 {
6144 gl.texStorage2D(texture_target, m_reference_texture_n_mipmaps, GL_RGBA8, m_reference_texture_width,
6145 m_reference_texture_height);
6146
6147 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
6148
6149 m_iteration_parent_texture_height = m_reference_texture_height;
6150 m_iteration_parent_texture_n_levels = m_reference_texture_n_mipmaps;
6151 m_iteration_parent_texture_width = m_reference_texture_width;
6152
6153 m_testCtx.getLog() << tcu::TestLog::Message
6154 << "Created an immutable parent texture object for texture target "
6155 << "[" << TextureViewUtilities::getTextureTargetString(texture_target) << "] "
6156 << "of "
6157 << "levels:[" << m_reference_texture_n_mipmaps << "] "
6158 << "width:[" << m_reference_texture_width << "] "
6159 << "height:[" << m_reference_texture_height << "]." << tcu::TestLog::EndMessage;
6160
6161 break;
6162 }
6163
6164 case GL_TEXTURE_RECTANGLE:
6165 {
6166 gl.texStorage2D(texture_target, 1, /* rectangle textures do not use mip-maps */
6167 GL_RGBA8, m_reference_texture_width, m_reference_texture_height);
6168
6169 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
6170
6171 m_iteration_parent_texture_height = m_reference_texture_height;
6172 m_iteration_parent_texture_width = m_reference_texture_width;
6173
6174 m_testCtx.getLog() << tcu::TestLog::Message
6175 << "Created an immutable parent texture object for texture target "
6176 << "[" << TextureViewUtilities::getTextureTargetString(texture_target) << "] "
6177 << "of "
6178 << "levels:1 "
6179 << "width:[" << m_reference_texture_width << "] "
6180 << "height:[" << m_reference_texture_height << "]." << tcu::TestLog::EndMessage;
6181
6182 break;
6183 }
6184
6185 case GL_TEXTURE_2D_ARRAY:
6186 {
6187 gl.texStorage3D(texture_target, m_reference_texture_n_mipmaps, GL_RGBA8, m_reference_texture_width,
6188 m_reference_texture_height, texture_depth);
6189
6190 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage3D() call failed.");
6191
6192 m_iteration_parent_texture_depth = texture_depth;
6193 m_iteration_parent_texture_height = m_reference_texture_height;
6194 m_iteration_parent_texture_n_levels = m_reference_texture_n_mipmaps;
6195 m_iteration_parent_texture_width = m_reference_texture_width;
6196
6197 m_testCtx.getLog() << tcu::TestLog::Message
6198 << "Created an immutable parent texture object for texture target "
6199 << "[" << TextureViewUtilities::getTextureTargetString(texture_target) << "] "
6200 << "of "
6201 << "depth:[" << texture_depth << "] "
6202 << "levels:[" << m_reference_texture_n_mipmaps << "] "
6203 << "width:[" << m_reference_texture_width << "] "
6204 << "height:[" << m_reference_texture_height << "]." << tcu::TestLog::EndMessage;
6205
6206 break;
6207 }
6208
6209 case GL_TEXTURE_2D_MULTISAMPLE:
6210 {
6211 gl.texStorage2DMultisample(texture_target, m_max_color_texture_samples_gl_value, GL_RGBA8,
6212 m_reference_texture_width, m_reference_texture_height,
6213 GL_TRUE); /* fixedsamplelocations */
6214
6215 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample() call failed.");
6216
6217 m_iteration_parent_texture_height = m_reference_texture_height;
6218 m_iteration_parent_texture_n_samples = m_max_color_texture_samples_gl_value;
6219 m_iteration_parent_texture_width = m_reference_texture_width;
6220
6221 m_testCtx.getLog() << tcu::TestLog::Message
6222 << "Created an immutable parent texture object for texture target "
6223 << "[" << TextureViewUtilities::getTextureTargetString(texture_target) << "] "
6224 << "of "
6225 << "samples:[" << m_max_color_texture_samples_gl_value << "] "
6226 << "width:[" << m_reference_texture_width << "] "
6227 << "height:[" << m_reference_texture_height << "]." << tcu::TestLog::EndMessage;
6228
6229 break;
6230 }
6231
6232 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
6233 {
6234 gl.texStorage3DMultisample(texture_target, m_max_color_texture_samples_gl_value, GL_RGBA8,
6235 m_reference_texture_width, m_reference_texture_height, texture_depth,
6236 GL_TRUE); /* fixed sample locations */
6237
6238 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage3DMultisample() call failed.");
6239
6240 m_iteration_parent_texture_depth = texture_depth;
6241 m_iteration_parent_texture_height = m_reference_texture_height;
6242 m_iteration_parent_texture_n_samples = m_max_color_texture_samples_gl_value;
6243 m_iteration_parent_texture_width = m_reference_texture_width;
6244
6245 m_testCtx.getLog() << tcu::TestLog::Message
6246 << "Created an immutable parent texture object for texture target "
6247 << "[" << TextureViewUtilities::getTextureTargetString(texture_target) << "] "
6248 << "of "
6249 << "samples:[" << m_max_color_texture_samples_gl_value << "] "
6250 << "width:[" << m_reference_texture_width << "] "
6251 << "height:[" << m_reference_texture_height << "] "
6252 << "depth:[" << texture_depth << "]." << tcu::TestLog::EndMessage;
6253
6254 break;
6255 }
6256
6257 case GL_TEXTURE_3D:
6258 case GL_TEXTURE_CUBE_MAP_ARRAY:
6259 {
6260 gl.texStorage3D(texture_target, m_reference_texture_n_mipmaps, GL_RGBA8, m_reference_texture_width,
6261 m_reference_texture_height, texture_depth);
6262
6263 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage3D() call failed.");
6264
6265 m_iteration_parent_texture_depth = texture_depth;
6266 m_iteration_parent_texture_height = m_reference_texture_height;
6267 m_iteration_parent_texture_n_levels = m_reference_texture_n_mipmaps;
6268 m_iteration_parent_texture_width = m_reference_texture_width;
6269
6270 m_testCtx.getLog() << tcu::TestLog::Message
6271 << "Created an immutable parent texture object for texture target "
6272 << "[" << TextureViewUtilities::getTextureTargetString(texture_target) << "] "
6273 << "of "
6274 << "levels:[" << m_reference_texture_n_mipmaps << "] "
6275 << "width:[" << m_reference_texture_width << "] "
6276 << "height:[" << m_reference_texture_height << "] "
6277 << "depth:[" << texture_depth << "]." << tcu::TestLog::EndMessage;
6278
6279 break;
6280 }
6281
6282 default:
6283 {
6284 TCU_FAIL("Unrecognized texture target.");
6285 }
6286 } /* switch (texture_target) */
6287
6288 m_iteration_parent_texture_target = texture_target;
6289 }
6290
6291 /* Configure texture filtering */
6292 if (texture_target != GL_TEXTURE_2D_MULTISAMPLE && texture_target != GL_TEXTURE_2D_MULTISAMPLE_ARRAY &&
6293 texture_target != GL_TEXTURE_RECTANGLE)
6294 {
6295 gl.texParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6296 gl.texParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
6297
6298 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() call(s) failed.");
6299 }
6300 }
6301
6302 /** Executes test iteration.
6303 *
6304 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
6305 */
iterate()6306 tcu::TestNode::IterateResult TextureViewTestViewSampling::iterate()
6307 {
6308 bool has_failed = false;
6309
6310 /* Make sure GL_ARB_texture_view is reported as supported before carrying on
6311 * with actual execution */
6312 const std::vector<std::string> &extensions = m_context.getContextInfo().getExtensions();
6313
6314 if (std::find(extensions.begin(), extensions.end(), "GL_ARB_texture_view") == extensions.end())
6315 {
6316 throw tcu::NotSupportedError("GL_ARB_texture_view is not supported");
6317 }
6318
6319 /* Initialize all objects required to run the test */
6320 initTest();
6321
6322 /* Initialize per-sample filler program */
6323 initPerSampleFillerProgramObject();
6324
6325 /* Iterate through all texture/view texture target combinations */
6326 TextureViewUtilities::_compatible_texture_target_pairs_const_iterator texture_target_iterator;
6327 TextureViewUtilities::_compatible_texture_target_pairs texture_target_pairs =
6328 TextureViewUtilities::getLegalTextureAndViewTargetCombinations();
6329
6330 for (texture_target_iterator = texture_target_pairs.begin(); texture_target_iterator != texture_target_pairs.end();
6331 ++texture_target_iterator)
6332 {
6333 const glw::GLenum parent_texture_target = texture_target_iterator->first;
6334 const glw::GLenum view_texture_target = texture_target_iterator->second;
6335
6336 /* Initialize parent texture */
6337 initTextureObject(false /* is_view_texture */, parent_texture_target, view_texture_target);
6338
6339 /* Initialize view */
6340 initTextureObject(true /* is_view_texture */, parent_texture_target, view_texture_target);
6341
6342 /* Initialize contents of the parent texture */
6343 initParentTextureContents();
6344
6345 /* Initialize iteration-specific test program object */
6346 initIterationSpecificProgramObject();
6347
6348 /* Run the actual test */
6349 bool status = executeTest();
6350
6351 if (!status)
6352 {
6353 has_failed = true;
6354
6355 m_testCtx.getLog() << tcu::TestLog::Message << "Test case failed." << tcu::TestLog::EndMessage;
6356 }
6357 else
6358 {
6359 m_testCtx.getLog() << tcu::TestLog::Message << "Test case succeeded." << tcu::TestLog::EndMessage;
6360 }
6361 }
6362
6363 if (!has_failed)
6364 {
6365 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
6366 }
6367 else
6368 {
6369 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
6370 }
6371
6372 return STOP;
6373 }
6374
6375 /** De-allocates existing reference color storage (if one already exists) and
6376 * allocates a new one using user-provided properties.
6377 *
6378 * @param n_layers Amount of layers to consider. Use a value of 1 for non-arrayed
6379 * texture targets.
6380 * @param n_faces Amount of faces to consider. Use a value of 1 for non-CM
6381 * texture targets.
6382 * @param n_mipmaps Amount of mip-maps to consider. Use a value of 1 for non-mipmapped
6383 * texture targets.
6384 * @param n_samples Amount of samples to consider. Use a value of 1 for single-sampled
6385 * texture targets.
6386 **/
resetReferenceColorStorage(unsigned int n_layers,unsigned int n_faces,unsigned int n_mipmaps,unsigned int n_samples)6387 void TextureViewTestViewSampling::resetReferenceColorStorage(unsigned int n_layers, unsigned int n_faces,
6388 unsigned int n_mipmaps, unsigned int n_samples)
6389 {
6390 /* Quick checks */
6391 DE_ASSERT(n_layers >= 1);
6392 DE_ASSERT(n_faces >= 1);
6393 DE_ASSERT(n_mipmaps >= 1);
6394 DE_ASSERT(n_samples >= 1);
6395
6396 /* Allocate the descriptor if it's the first time the test will be
6397 * attempting to access it */
6398 if (m_reference_color_storage == DE_NULL)
6399 {
6400 m_reference_color_storage = new _reference_color_storage(n_faces, n_layers, n_mipmaps, n_samples);
6401 }
6402 else
6403 {
6404 /* The descriptor's already there so we only need to update the properties */
6405 m_reference_color_storage->n_faces = n_faces;
6406 m_reference_color_storage->n_layers = n_layers;
6407 m_reference_color_storage->n_mipmaps = n_mipmaps;
6408 m_reference_color_storage->n_samples = n_samples;
6409 }
6410
6411 /* If there's any data descriptor found allocated at this point,
6412 * release it */
6413 if (m_reference_color_storage->data != DE_NULL)
6414 {
6415 delete[] m_reference_color_storage->data;
6416
6417 m_reference_color_storage->data = DE_NULL;
6418 }
6419
6420 m_reference_color_storage->data = new tcu::Vec4[n_layers * n_faces * n_mipmaps * n_samples];
6421 }
6422
6423 /** Assigns user-specified reference color to a specific sample of a layer/face's mip-map.
6424 *
6425 * This function throws an assertion failure if the requested layer/face/mip-map/sample index
6426 * is invalid.
6427 *
6428 * @param n_layer Layer index to use for the association. Use a value of 0 for non-arrayed texture
6429 * targets.
6430 * @param n_face Face index to use for the association. Use a value of 0 for non-CM texture targets.
6431 * @param n_mipmap Mip-map index to use for the association. Use a value of 0 for non-mipmapped texture
6432 * targets.
6433 * @param n_sample Sample index to use for the association. Use a value of 0 for single-sampled texture
6434 * targets.
6435 * @param color Color to associate with the specified sample.
6436 **/
setReferenceColor(unsigned int n_layer,unsigned int n_face,unsigned int n_mipmap,unsigned int n_sample,tcu::Vec4 color)6437 void TextureViewTestViewSampling::setReferenceColor(unsigned int n_layer, unsigned int n_face, unsigned int n_mipmap,
6438 unsigned int n_sample, tcu::Vec4 color)
6439 {
6440 DE_ASSERT(m_reference_color_storage != DE_NULL);
6441 if (m_reference_color_storage != DE_NULL)
6442 {
6443 DE_ASSERT(n_face < m_reference_color_storage->n_faces);
6444 DE_ASSERT(n_layer < m_reference_color_storage->n_layers);
6445 DE_ASSERT(n_mipmap < m_reference_color_storage->n_mipmaps);
6446 DE_ASSERT(n_sample < m_reference_color_storage->n_samples);
6447
6448 /* Hierarchy is:
6449 *
6450 * layers -> faces -> mipmaps -> samples */
6451 const unsigned int index =
6452 n_layer * (m_reference_color_storage->n_faces * m_reference_color_storage->n_mipmaps *
6453 m_reference_color_storage->n_samples) +
6454 n_face * (m_reference_color_storage->n_mipmaps * m_reference_color_storage->n_samples) +
6455 n_mipmap * (m_reference_color_storage->n_samples) + n_sample;
6456
6457 m_reference_color_storage->data[index] = color;
6458 }
6459 }
6460
6461 /** Constructor.
6462 *
6463 * @param context Rendering context.
6464 **/
TextureViewTestViewClasses(deqp::Context & context)6465 TextureViewTestViewClasses::TextureViewTestViewClasses(deqp::Context &context)
6466 : TestCase(context, "view_classes",
6467 "Verifies view sampling works correctly. Tests all valid"
6468 " texture/view internalformat combinations.")
6469 , m_bo_id(0)
6470 , m_po_id(0)
6471 , m_to_id(0)
6472 , m_to_temp_id(0)
6473 , m_vao_id(0)
6474 , m_view_to_id(0)
6475 , m_vs_id(0)
6476 , m_decompressed_mipmap_data(DE_NULL)
6477 , m_mipmap_data(DE_NULL)
6478 , m_bo_size(0)
6479 , m_has_test_failed(false)
6480 , m_texture_height(4)
6481 , m_texture_unit_for_parent_texture(GL_TEXTURE0)
6482 , m_texture_unit_for_view_texture(GL_TEXTURE1)
6483 , m_texture_width(4)
6484 , m_view_data_offset(0)
6485 {
6486 /* Left blank on purpose */
6487 }
6488
6489 /** Deinitializes all buffers and GL objects that may have been created
6490 * during test execution. Also restores GL state that may have been modified.
6491 **/
deinit()6492 void TextureViewTestViewClasses::deinit()
6493 {
6494 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
6495
6496 if (m_bo_id != 0)
6497 {
6498 gl.deleteBuffers(1, &m_bo_id);
6499
6500 m_bo_id = 0;
6501 }
6502
6503 if (m_decompressed_mipmap_data != DE_NULL)
6504 {
6505 delete[] m_decompressed_mipmap_data;
6506
6507 m_decompressed_mipmap_data = DE_NULL;
6508 }
6509
6510 if (m_mipmap_data != DE_NULL)
6511 {
6512 delete[] m_mipmap_data;
6513
6514 m_mipmap_data = DE_NULL;
6515 }
6516
6517 if (m_po_id != 0)
6518 {
6519 gl.deleteProgram(m_po_id);
6520
6521 m_po_id = 0;
6522 }
6523
6524 if (m_to_id != 0)
6525 {
6526 gl.deleteTextures(1, &m_to_id);
6527
6528 m_to_id = 0;
6529 }
6530
6531 if (m_to_temp_id != 0)
6532 {
6533 gl.deleteTextures(1, &m_to_temp_id);
6534
6535 m_to_temp_id = 0;
6536 }
6537
6538 if (m_vao_id != 0)
6539 {
6540 gl.deleteVertexArrays(1, &m_vao_id);
6541
6542 m_vao_id = 0;
6543 }
6544
6545 if (m_view_to_id != 0)
6546 {
6547 gl.deleteTextures(1, &m_view_to_id);
6548
6549 m_view_to_id = 0;
6550 }
6551
6552 if (m_vs_id != 0)
6553 {
6554 gl.deleteShader(m_vs_id);
6555
6556 m_vs_id = 0;
6557 }
6558
6559 /* Bring back the default pixel storage settings that the test may have modified. */
6560 gl.pixelStorei(GL_PACK_ALIGNMENT, 4);
6561 gl.pixelStorei(GL_UNPACK_ALIGNMENT, 4);
6562
6563 /* Restore rasterization */
6564 gl.enable(GL_RASTERIZER_DISCARD);
6565 }
6566
6567 /** Reads user-specified amount of components and stores it in user-provided location,
6568 * according to user-defined format (snorm, unorm, etc.) and component size.
6569 *
6570 * This function assumes component sizes are aligned on by boundary (that is: size % 8
6571 * equals 0 for all components). An assertion failure will occur if this requirement is
6572 * not met.
6573 * This function throws TestError exception if any of the requested component sizes
6574 * or format is not supported.
6575 *
6576 * @param data Raw data buffer to read the data from.
6577 * @param n_components Amount of components to read.
6578 * @param component_sizes 4 ints subsequently defining component size for R/G/B/A channels.
6579 * Must not be NULL.
6580 * @param format Format to be used for data retrieval. This defines data format of
6581 * the underlying components (for instance: for UNORMs we need to
6582 * divide the read ubyte/ushort/uint data by maximum value allowed for
6583 * the type minus one)
6584 * @param result Location to store the read components. Must not be NULL. Must be
6585 * large enough to hold requested amount of components of user-specified
6586 * component size.
6587 *
6588 **/
getComponentDataForByteAlignedInternalformat(const unsigned char * data,const unsigned int n_components,const unsigned int * component_sizes,const _format format,void * result)6589 void TextureViewTestViewClasses::getComponentDataForByteAlignedInternalformat(const unsigned char *data,
6590 const unsigned int n_components,
6591 const unsigned int *component_sizes,
6592 const _format format, void *result)
6593 {
6594 float *result_float = (float *)result;
6595 signed int *result_sint = (signed int *)result;
6596 unsigned int *result_uint = (unsigned int *)result;
6597
6598 /* Quick checks: we assume the components are aligned on byte boundary. */
6599 DE_ASSERT((component_sizes[0] % 8) == 0 && (component_sizes[1] % 8) == 0 && (component_sizes[2] % 8) == 0 &&
6600 (component_sizes[3] % 8) == 0);
6601
6602 for (unsigned int n_component = 0; n_component < n_components;
6603 data += (component_sizes[n_component] >> 3 /* 8 bits/byte */), ++n_component)
6604 {
6605 switch (format)
6606 {
6607 case FORMAT_FLOAT:
6608 {
6609 switch (component_sizes[n_component])
6610 {
6611 case 16:
6612 result_float[n_component] = deFloat16To32(*(const deFloat16 *)data);
6613 break;
6614 case 32:
6615 result_float[n_component] = *(float *)data;
6616 break;
6617
6618 default:
6619 TCU_FAIL("Unsupported component size");
6620 }
6621
6622 break;
6623 }
6624
6625 case FORMAT_SIGNED_INTEGER:
6626 {
6627 switch (component_sizes[n_component])
6628 {
6629 case 8:
6630 result_sint[n_component] = *(signed char *)data;
6631 break;
6632 case 16:
6633 result_sint[n_component] = *(signed short *)data;
6634 break;
6635 case 32:
6636 result_sint[n_component] = *(signed int *)data;
6637 break;
6638
6639 default:
6640 TCU_FAIL("Unsupported component size");
6641 }
6642
6643 break;
6644 }
6645
6646 case FORMAT_SNORM:
6647 {
6648 switch (component_sizes[n_component])
6649 {
6650 case 8:
6651 result_float[n_component] = float(*(signed char *)data) / 127.0f;
6652 break;
6653 case 16:
6654 result_float[n_component] = float(*(signed short *)data) / 32767.0f;
6655 break;
6656
6657 default:
6658 TCU_FAIL("Unsupported component size");
6659 }
6660
6661 if (result_float[n_component] < -1.0f)
6662 {
6663 result_float[n_component] = -1.0f;
6664 }
6665
6666 break;
6667 }
6668
6669 case FORMAT_UNORM:
6670 {
6671 switch (component_sizes[n_component])
6672 {
6673 case 8:
6674 result_float[n_component] = float(*((unsigned char *)data)) / 255.0f;
6675 break;
6676 case 16:
6677 result_float[n_component] = float(*((unsigned short *)data)) / 65535.0f;
6678 break;
6679
6680 default:
6681 TCU_FAIL("Unsupported component size");
6682 }
6683
6684 break;
6685 }
6686
6687 case FORMAT_UNSIGNED_INTEGER:
6688 {
6689 switch (component_sizes[n_component])
6690 {
6691 case 8:
6692 result_uint[n_component] = *(unsigned char *)data;
6693 break;
6694 case 16:
6695 result_uint[n_component] = *(unsigned short *)data;
6696 break;
6697 case 32:
6698 result_uint[n_component] = *(unsigned int *)data;
6699 break;
6700
6701 default:
6702 TCU_FAIL("Unsupported component size");
6703 }
6704
6705 break;
6706 }
6707
6708 default:
6709 {
6710 TCU_FAIL("Unrecognized mip-map format");
6711 }
6712 } /* switch (view_format) */
6713 } /* for (all components) */
6714 }
6715
6716 /** Initializes buffer object storage of sufficient size to hold data that will be
6717 * XFBed out by the test's vertex shader, given user-specified parent texture &
6718 * view's internalformats.
6719 *
6720 * Throws TestError exceptions if GL calls fail.
6721 *
6722 * @param texture_internalformat Internalformat used by the parent texture object,
6723 * from which the view will be created.
6724 * @param view_internalformat Internalformat that will be used by the texture view.
6725 **/
initBufferObject(glw::GLenum texture_internalformat,glw::GLenum view_internalformat)6726 void TextureViewTestViewClasses::initBufferObject(glw::GLenum texture_internalformat, glw::GLenum view_internalformat)
6727 {
6728 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
6729
6730 /* Calculate how much size we will need to read the XFBed data. Each sampled data
6731 * will either end up stored in a vecX, ivecX or uvecX (where X stands for amount
6732 * of components supported by considered internalformat), so we can assume it will
6733 * take a sizeof(float) = sizeof(int) = sizeof(unsigned int)
6734 */
6735 const unsigned int parent_texture_n_components =
6736 TextureViewUtilities::getAmountOfComponentsForInternalformat(texture_internalformat);
6737 const unsigned int view_texture_n_components =
6738 TextureViewUtilities::getAmountOfComponentsForInternalformat(view_internalformat);
6739
6740 /* Configure buffer object storage.
6741 *
6742 * NOTE: We do not care about the data type of the stored data, since sizes of the
6743 * types we're interested in (floats, ints and uints) match.
6744 */
6745 DE_ASSERT(sizeof(float) == sizeof(unsigned int) && sizeof(float) == sizeof(int));
6746
6747 m_bo_size =
6748 static_cast<unsigned int>(parent_texture_n_components * sizeof(float) * m_texture_height * m_texture_width +
6749 view_texture_n_components * sizeof(float) * m_texture_height * m_texture_width);
6750
6751 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_size, DE_NULL, /* data */
6752 GL_STATIC_DRAW);
6753 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
6754
6755 /* For XFB, we'll be outputting data sampled from both the texture and the view.
6756 * Sampled texture data will go to the first half of the buffer, and the corresponding
6757 * view data will go to the one half.
6758 *
6759 * Store the offset, from which the view's data will start so that we can correctly
6760 * configure buffer object bindings in initProgramObject()
6761 **/
6762 m_view_data_offset =
6763 static_cast<unsigned int>(parent_texture_n_components * sizeof(float) * m_texture_height * m_texture_width);
6764 }
6765
6766 /** Initializes a program object that should be used for the test, given
6767 * user-specified texture and view internalformats.
6768 *
6769 * @param texture_internalformat Internalformat used by the parent texture object,
6770 * from which the view will be created.
6771 * @param view_internalformat Internalformat that will be used by the texture view.
6772 **/
initProgramObject(glw::GLenum texture_internalformat,glw::GLenum view_internalformat)6773 void TextureViewTestViewClasses::initProgramObject(glw::GLenum texture_internalformat, glw::GLenum view_internalformat)
6774 {
6775 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
6776
6777 /* Determine which samplers we should be using for sampling both textures */
6778 const unsigned int texture_n_components =
6779 TextureViewUtilities::getAmountOfComponentsForInternalformat(texture_internalformat);
6780 const _sampler_type texture_sampler_type =
6781 TextureViewUtilities::getSamplerTypeForInternalformat(texture_internalformat);
6782 const char *texture_sampler_data_type_glsl =
6783 TextureViewUtilities::getGLSLDataTypeForSamplerType(texture_sampler_type, texture_n_components);
6784 const char *texture_sampler_glsl = TextureViewUtilities::getGLSLTypeForSamplerType(texture_sampler_type);
6785 const char *texture_swizzle_glsl = (texture_n_components == 4) ? "xyzw" :
6786 (texture_n_components == 3) ? "xyz" :
6787 (texture_n_components == 2) ? "xy" :
6788 "x";
6789 const unsigned int view_n_components =
6790 TextureViewUtilities::getAmountOfComponentsForInternalformat(view_internalformat);
6791 const _sampler_type view_sampler_type = TextureViewUtilities::getSamplerTypeForInternalformat(view_internalformat);
6792 const char *view_sampler_data_type_glsl =
6793 TextureViewUtilities::getGLSLDataTypeForSamplerType(view_sampler_type, view_n_components);
6794 const char *view_sampler_glsl = TextureViewUtilities::getGLSLTypeForSamplerType(view_sampler_type);
6795 const char *view_swizzle_glsl = (view_n_components == 4) ? "xyzw" :
6796 (view_n_components == 3) ? "xyz" :
6797 (view_n_components == 2) ? "xy" :
6798 "x";
6799
6800 /* Form vertex shader body */
6801 const char *token_texture_data_type = "TEXTURE_DATA_TYPE";
6802 const char *token_texture_sampler = "TEXTURE_SAMPLER";
6803 const char *token_texture_swizzle = "TEXTURE_SWIZZLE";
6804 const char *token_view_data_type = "VIEW_DATA_TYPE";
6805 const char *token_view_sampler = "VIEW_SAMPLER";
6806 const char *token_view_swizzle = "VIEW_SWIZZLE";
6807 const char *vs_template_body = "#version 400\n"
6808 "\n"
6809 "uniform TEXTURE_SAMPLER texture;\n"
6810 "uniform VIEW_SAMPLER view;\n"
6811 "\n"
6812 "out TEXTURE_DATA_TYPE out_texture_data;\n"
6813 "out VIEW_DATA_TYPE out_view_data;\n"
6814 "\n"
6815 "void main()\n"
6816 "{\n"
6817 " ivec2 uv = ivec2(gl_VertexID % 4,\n"
6818 " gl_VertexID / 4);\n"
6819 "\n"
6820 " out_texture_data = texelFetch(texture, uv, 0).TEXTURE_SWIZZLE;\n"
6821 " out_view_data = texelFetch(view, uv, 0).VIEW_SWIZZLE;\n"
6822 "}\n";
6823
6824 std::size_t token_position = std::string::npos;
6825 std::string vs_body = vs_template_body;
6826
6827 while ((token_position = vs_body.find(token_texture_data_type)) != std::string::npos)
6828 {
6829 vs_body.replace(token_position, strlen(token_texture_data_type), texture_sampler_data_type_glsl);
6830 }
6831
6832 while ((token_position = vs_body.find(token_texture_sampler)) != std::string::npos)
6833 {
6834 vs_body.replace(token_position, strlen(token_texture_sampler), texture_sampler_glsl);
6835 }
6836
6837 while ((token_position = vs_body.find(token_texture_swizzle)) != std::string::npos)
6838 {
6839 vs_body.replace(token_position, strlen(token_texture_swizzle), texture_swizzle_glsl);
6840 }
6841
6842 while ((token_position = vs_body.find(token_view_data_type)) != std::string::npos)
6843 {
6844 vs_body.replace(token_position, strlen(token_view_data_type), view_sampler_data_type_glsl);
6845 }
6846
6847 while ((token_position = vs_body.find(token_view_sampler)) != std::string::npos)
6848 {
6849 vs_body.replace(token_position, strlen(token_view_sampler), view_sampler_glsl);
6850 }
6851
6852 while ((token_position = vs_body.find(token_view_swizzle)) != std::string::npos)
6853 {
6854 vs_body.replace(token_position, strlen(token_view_swizzle), view_swizzle_glsl);
6855 }
6856
6857 /* Compile the shader */
6858 glw::GLint compile_status = GL_FALSE;
6859 const char *vs_body_raw_ptr = vs_body.c_str();
6860
6861 gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
6862 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6863
6864 gl.compileShader(m_vs_id);
6865 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
6866
6867 gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
6868 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
6869
6870 if (compile_status != GL_TRUE)
6871 {
6872 TCU_FAIL("Shader compilation failed");
6873 }
6874
6875 /* Configure test program object for XFB */
6876 const char *varying_names[] = {"out_texture_data", "out_view_data"};
6877 const unsigned int n_varying_names = sizeof(varying_names) / sizeof(varying_names[0]);
6878
6879 gl.transformFeedbackVaryings(m_po_id, n_varying_names, varying_names, GL_SEPARATE_ATTRIBS);
6880 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
6881
6882 /* Configure buffer object bindings for XFB */
6883 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* index for 'out_texture_data' */
6884 m_bo_id, 0, /* offset */
6885 m_view_data_offset); /* size */
6886 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 1, /* index for 'out_view_data' */
6887 m_bo_id, m_view_data_offset, /* offset */
6888 m_bo_size - m_view_data_offset); /* size */
6889
6890 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange() call(s) failed.");
6891
6892 /* Link the program object */
6893 glw::GLint link_status = GL_FALSE;
6894
6895 gl.linkProgram(m_po_id);
6896 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
6897
6898 gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
6899 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
6900
6901 if (link_status != GL_TRUE)
6902 {
6903 TCU_FAIL("Program linking failed.");
6904 }
6905
6906 /* Configure sampler uniforms */
6907 glw::GLint texture_uniform_location = gl.getUniformLocation(m_po_id, "texture");
6908 glw::GLint view_uniform_location = gl.getUniformLocation(m_po_id, "view");
6909
6910 if (texture_uniform_location == -1)
6911 {
6912 TCU_FAIL("'texture' uniform is considered inactive which is invalid");
6913 }
6914
6915 if (view_uniform_location == -1)
6916 {
6917 TCU_FAIL("'view' uniform is considered inactive which is invalid");
6918 }
6919
6920 gl.useProgram(m_po_id);
6921 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
6922
6923 gl.uniform1i(texture_uniform_location, m_texture_unit_for_parent_texture - GL_TEXTURE0);
6924 gl.uniform1i(view_uniform_location, m_texture_unit_for_view_texture - GL_TEXTURE0);
6925 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i() call(s) failed.");
6926 }
6927
6928 /** Creates GL objects required to run the test, as well as modifies GL
6929 * configuration (pixel pack/unpack settings, enables 'rasterizer discard' mode)
6930 * in order for the test to run properly.
6931 **/
initTest()6932 void TextureViewTestViewClasses::initTest()
6933 {
6934 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
6935
6936 /* Generate objects that will be used by all test iterations.
6937 *
6938 * Note that we're not generating texture objects here. This is owing to the fact
6939 * we'll be using immutable textures and it makes more sense to generate the objects
6940 * in initTexture() instead.
6941 **/
6942 gl.genBuffers(1, &m_bo_id);
6943 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
6944
6945 m_po_id = gl.createProgram();
6946 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
6947
6948 gl.genVertexArrays(1, &m_vao_id);
6949 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
6950
6951 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
6952 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
6953
6954 /* Attach the vertex shader to the program object */
6955 gl.attachShader(m_po_id, m_vs_id);
6956 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
6957
6958 /* Configure general buffer object binding. Indiced bindings will be configured
6959 * in initProgramObject()
6960 */
6961 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id);
6962 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
6963
6964 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_bo_id);
6965 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
6966
6967 /* Bind the VAO */
6968 gl.bindVertexArray(m_vao_id);
6969 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
6970
6971 /* Modify pack & unpack alignment settings */
6972 gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
6973 gl.pixelStorei(GL_UNPACK_ALIGNMENT, 1);
6974 GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call(s) failed.");
6975
6976 /* Disable rasterizatino */
6977 gl.enable(GL_RASTERIZER_DISCARD);
6978 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_RASTERIZER_DISCARD) call failed.");
6979 }
6980
6981 /** Generates and initializes storage of either the parent texture object or the
6982 * texture view, using user-specified internalformat.
6983 *
6984 * @param should_init_parent_texture true to initialize parent texture object storage,
6985 * false to configure texture view.
6986 * @param internalformat Internalformat to use for the process.
6987 * @param viewformat Internalformat that will be used by "view" texture.
6988 *
6989 **/
initTextureObject(bool should_init_parent_texture,glw::GLenum texture_internalformat,glw::GLenum view_internalformat)6990 void TextureViewTestViewClasses::initTextureObject(bool should_init_parent_texture, glw::GLenum texture_internalformat,
6991 glw::GLenum view_internalformat)
6992 {
6993 glw::GLenum cached_view_internalformat = view_internalformat;
6994 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
6995 glw::GLuint *to_id_ptr = (should_init_parent_texture) ? &m_to_id : &m_view_to_id;
6996
6997 /* If the object we're about to initialize has already been created, delete it first. */
6998 if (*to_id_ptr != 0)
6999 {
7000 gl.deleteTextures(1, to_id_ptr);
7001 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures() call failed.");
7002
7003 *to_id_ptr = 0;
7004 }
7005
7006 /* Generate a new texture object */
7007 gl.genTextures(1, to_id_ptr);
7008
7009 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed.");
7010
7011 /* Initialize the object */
7012 if (should_init_parent_texture)
7013 {
7014 gl.bindTexture(GL_TEXTURE_2D, *to_id_ptr);
7015 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
7016
7017 gl.texStorage2D(GL_TEXTURE_2D, 1, /* levels */
7018 texture_internalformat, m_texture_width, m_texture_height);
7019
7020 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
7021 }
7022 else
7023 {
7024 gl.textureView(m_view_to_id, GL_TEXTURE_2D, m_to_id, view_internalformat, 0, /* minlevel */
7025 1, /* numlevels */
7026 0, /* minlayer */
7027 1); /* numlayers */
7028
7029 GLU_EXPECT_NO_ERROR(gl.getError(), "glTextureView() call failed.");
7030
7031 gl.bindTexture(GL_TEXTURE_2D, m_view_to_id);
7032 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
7033 }
7034
7035 if (should_init_parent_texture)
7036 {
7037 /* We need to fill the base mip-map with actual contents. Calculate how much
7038 * data we will need to fill a 4x4 mip-map, given the requested internalformat.
7039 */
7040 bool is_internalformat_compressed = TextureViewUtilities::isInternalformatCompressed(texture_internalformat);
7041 glw::GLenum internalformat_to_use = GL_NONE;
7042
7043 if (is_internalformat_compressed)
7044 {
7045 /* In order to initialize texture objects defined with a compressed internalformat
7046 * using raw decompressed data, we need to override caller-specified internalformat
7047 * with an internalformat that will describe decompressed data. The data will then
7048 * be converted by GL to the compressed internalformat that was used for the previous
7049 * glTexStorage2D() call.
7050 **/
7051 _format format = TextureViewUtilities::getFormatOfInternalformat(texture_internalformat);
7052
7053 if (format == FORMAT_FLOAT)
7054 {
7055 internalformat_to_use = GL_RGBA32F;
7056 }
7057 else
7058 {
7059 DE_ASSERT(format == FORMAT_UNORM || format == FORMAT_SNORM);
7060
7061 internalformat_to_use = GL_RGBA8;
7062 }
7063
7064 view_internalformat = internalformat_to_use;
7065 }
7066 else
7067 {
7068 internalformat_to_use = texture_internalformat;
7069 }
7070
7071 /* Allocate the buffer.
7072 *
7073 * NOTE: This buffer is used in verifyResults(). When no longer needed, it will either
7074 * be deallocated there or in deinit().
7075 **/
7076 glw::GLenum format_to_use = TextureViewUtilities::getGLFormatOfInternalformat(internalformat_to_use);
7077 glw::GLenum type_to_use = TextureViewUtilities::getTypeCompatibleWithInternalformat(internalformat_to_use);
7078 const glw::GLenum view_type = TextureViewUtilities::getTypeCompatibleWithInternalformat(view_internalformat);
7079
7080 /* For some internalformats, we need to use a special data type in order to avoid
7081 * implicit data conversion during glTexSubImage2D() call.
7082 */
7083 switch (texture_internalformat)
7084 {
7085 case GL_R11F_G11F_B10F:
7086 type_to_use = GL_UNSIGNED_INT_10F_11F_11F_REV;
7087 break;
7088 case GL_RGB9_E5:
7089 type_to_use = GL_UNSIGNED_INT_5_9_9_9_REV;
7090 break;
7091 case GL_RGB10_A2:
7092 type_to_use = GL_UNSIGNED_INT_2_10_10_10_REV;
7093 break;
7094
7095 /* Fall-through for other internalformats! */
7096 } /* switch (texture_internalformat) */
7097
7098 /* Carry on */
7099 const unsigned int mipmap_raw_size = TextureViewUtilities::getTextureDataSize(
7100 internalformat_to_use, type_to_use, m_texture_width, m_texture_height);
7101
7102 if (m_mipmap_data != NULL)
7103 {
7104 delete[] m_mipmap_data;
7105
7106 m_mipmap_data = NULL;
7107 }
7108
7109 m_mipmap_data = new unsigned char[mipmap_raw_size];
7110
7111 /* Prepare data for texture */
7112 memset(m_mipmap_data, 0, mipmap_raw_size);
7113
7114 switch (view_type)
7115 {
7116 case GL_BYTE:
7117 {
7118 glw::GLbyte *buffer = (glw::GLbyte *)m_mipmap_data;
7119 const glw::GLuint n_total_components = mipmap_raw_size / 1;
7120
7121 for (glw::GLuint i = 0; i < n_total_components; ++i)
7122 {
7123 buffer[i] = static_cast<glw::GLbyte>(i - 128);
7124 }
7125
7126 break;
7127 }
7128
7129 case GL_SHORT:
7130 {
7131 glw::GLshort *buffer = (glw::GLshort *)m_mipmap_data;
7132 const glw::GLuint n_total_components = mipmap_raw_size / 2;
7133
7134 for (glw::GLuint i = 0; i < n_total_components; ++i)
7135 {
7136 buffer[i] = static_cast<glw::GLshort>(i - 0xC000); // 0xC000 = (fp16) -2 makes this non de-norm
7137 }
7138
7139 break;
7140 }
7141
7142 case GL_INT:
7143 {
7144 glw::GLint *buffer = (glw::GLint *)m_mipmap_data;
7145 const glw::GLuint n_total_components = mipmap_raw_size / 4;
7146
7147 for (glw::GLuint i = 0; i < n_total_components; ++i)
7148 {
7149 buffer[i] = i - 128;
7150 }
7151
7152 break;
7153 }
7154
7155 case GL_UNSIGNED_BYTE:
7156 {
7157 glw::GLubyte *buffer = (glw::GLubyte *)m_mipmap_data;
7158 const glw::GLuint n_total_components = mipmap_raw_size / 1;
7159
7160 for (glw::GLuint i = 0; i < n_total_components; ++i)
7161 {
7162 buffer[i] = static_cast<glw::GLubyte>(i);
7163 }
7164
7165 break;
7166 }
7167
7168 case GL_UNSIGNED_SHORT:
7169 {
7170 glw::GLushort *buffer = (glw::GLushort *)m_mipmap_data;
7171 const glw::GLuint n_total_components = mipmap_raw_size / 2;
7172
7173 for (glw::GLuint i = 0; i < n_total_components; ++i)
7174 {
7175 buffer[i] = static_cast<glw::GLushort>(i);
7176 }
7177
7178 break;
7179 }
7180
7181 case GL_UNSIGNED_INT:
7182 {
7183 glw::GLuint *buffer = (glw::GLuint *)m_mipmap_data;
7184 const glw::GLuint n_total_components = mipmap_raw_size / 4;
7185
7186 for (glw::GLuint i = 0; i < n_total_components; ++i)
7187 {
7188 buffer[i] = i;
7189 }
7190
7191 break;
7192 }
7193
7194 case GL_UNSIGNED_INT_24_8:
7195 {
7196 glw::GLuint *buffer = (glw::GLuint *)m_mipmap_data;
7197 const glw::GLuint n_total_components = mipmap_raw_size / 4;
7198
7199 for (glw::GLuint i = 0; i < n_total_components; ++i)
7200 {
7201 buffer[i] = (i << 8) | (0xaa);
7202 }
7203
7204 break;
7205 }
7206
7207 case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
7208 {
7209 glw::GLfloat *float_buffer = (glw::GLfloat *)m_mipmap_data;
7210 const glw::GLuint n_total_components = mipmap_raw_size / 8;
7211 glw::GLuint *uint_buffer = (glw::GLuint *)(m_mipmap_data + 4);
7212
7213 for (glw::GLuint i = 0; i < n_total_components; ++i)
7214 {
7215 float_buffer[i * 2] = (float)i - 128;
7216 uint_buffer[i * 2] = (i << 8) | (0xaa);
7217 }
7218
7219 break;
7220 }
7221
7222 case GL_HALF_FLOAT:
7223 {
7224 tcu::Float16 *buffer = (tcu::Float16 *)m_mipmap_data;
7225 const glw::GLuint n_total_components = mipmap_raw_size / 2;
7226
7227 for (glw::GLuint i = 0; i < n_total_components; ++i)
7228 {
7229 float value = (float)i - 128;
7230
7231 buffer[i] = (tcu::Float16)value;
7232 }
7233
7234 break;
7235 }
7236
7237 case GL_FLOAT:
7238 {
7239 glw::GLfloat *float_buffer = (glw::GLfloat *)m_mipmap_data;
7240 const glw::GLuint n_total_components = mipmap_raw_size / 4;
7241
7242 float offset = (cached_view_internalformat == GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT) ? 0.0f : -128.0f;
7243 for (glw::GLuint i = 0; i < n_total_components; ++i)
7244 {
7245 float_buffer[i] = (float)i + offset;
7246 }
7247
7248 break;
7249 }
7250
7251 case GL_UNSIGNED_INT_2_10_10_10_REV:
7252 {
7253 glw::GLuint *buffer = (glw::GLuint *)m_mipmap_data;
7254 const glw::GLuint n_total_components = mipmap_raw_size / 4;
7255
7256 for (glw::GLuint i = 0; i < n_total_components; ++i)
7257 {
7258 buffer[i] = i | (i << 8) | (i << 16);
7259 }
7260
7261 break;
7262 }
7263
7264 default:
7265 {
7266 TCU_FAIL("Unrecognized texture view type");
7267 }
7268 } /* switch (view_type) */
7269
7270 /* BPTC_FLOAT view class is a special case that needs an extra step. Signed and
7271 * unsigned internal formats use different encodings, so instead of passing
7272 * "regular" 32-bit floating-point data, we need to convert the values we initialized
7273 * above to an actual BPTC representation. Since the encodings differ, we should
7274 * compress these values using the internalformat that we will be later using for the
7275 * texture view.
7276 */
7277 unsigned int imageSize_to_use = 0;
7278 bool use_glCompressedTexSubImage2D_call = false;
7279
7280 if ((cached_view_internalformat == GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT ||
7281 cached_view_internalformat == GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT) &&
7282 cached_view_internalformat != texture_internalformat)
7283 {
7284 /* Create a temporary texture object we'll use to compress the floating-point data. */
7285 gl.genTextures(1, &m_to_temp_id);
7286 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed.");
7287
7288 gl.bindTexture(GL_TEXTURE_2D, m_to_temp_id);
7289 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
7290
7291 /* Initialize compressed storage */
7292 gl.texStorage2D(GL_TEXTURE_2D, 1, /* levels */
7293 cached_view_internalformat, m_texture_width, m_texture_height);
7294 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
7295
7296 /* Submit floating-point decompressed data */
7297 gl.texSubImage2D(GL_TEXTURE_2D, 0, /* level */
7298 0, /* xoffset */
7299 0, /* yoffset */
7300 m_texture_width, m_texture_height, GL_RGB, GL_FLOAT, m_mipmap_data);
7301 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexSubImage2D() call failed.");
7302
7303 /* Extract the compressed version */
7304 gl.getCompressedTexImage(GL_TEXTURE_2D, 0, /* level */
7305 m_mipmap_data);
7306 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetCompressedTexImage() call failed.");
7307
7308 /* Delete the temporary texture object */
7309 gl.deleteTextures(1, &m_to_temp_id);
7310 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures() call failed.");
7311
7312 m_to_temp_id = 0;
7313
7314 /* Revert to previous 2D texture binding */
7315 gl.bindTexture(GL_TEXTURE_2D, m_to_id);
7316 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
7317
7318 /* Make sure upcoming glCompressedTexSubImage2D() call is made with sensible arguments */
7319 imageSize_to_use = (unsigned int)ceil((float)m_texture_width / 4.0f) *
7320 (unsigned int)ceil((float)m_texture_height / 4.0f) * 16; /* block size */
7321 use_glCompressedTexSubImage2D_call = true;
7322 }
7323
7324 /* Fill the mip-map with data */
7325 if (use_glCompressedTexSubImage2D_call)
7326 {
7327 gl.compressedTexSubImage2D(GL_TEXTURE_2D, 0, /* level */
7328 0, /* xoffset */
7329 0, /* yoffset */
7330 m_texture_width, m_texture_height, texture_internalformat, imageSize_to_use,
7331 m_mipmap_data);
7332 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompressedTexSubImage2D() call failed.");
7333 }
7334 else
7335 {
7336 gl.texSubImage2D(GL_TEXTURE_2D, 0, /* level */
7337 0, /* xoffset */
7338 0, /* yoffset */
7339 m_texture_width, m_texture_height, format_to_use, type_to_use, m_mipmap_data);
7340
7341 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexSubImage2D() call failed.");
7342 }
7343 }
7344
7345 /* Make sure the texture object is complete */
7346 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
7347 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7348 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
7349 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
7350 GL_NEAREST); /* we're using texelFetch() so no mipmaps needed */
7351 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
7352 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
7353
7354 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() call(s) failed.");
7355 }
7356
7357 /** Executes test iteration.
7358 *
7359 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
7360 */
iterate()7361 tcu::TestNode::IterateResult TextureViewTestViewClasses::iterate()
7362 {
7363 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
7364
7365 /* Only execute the test if GL_ARB_texture_view is supported */
7366 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_texture_view"))
7367 {
7368 throw tcu::NotSupportedError("GL_ARB_texture_view is not supported, skipping.");
7369 }
7370
7371 /* Create all GL objects required to run the test */
7372 initTest();
7373
7374 /* Iterate through all valid "texture internalformat + view internalformat" combinations */
7375 TextureViewUtilities::_compatible_internalformat_pairs_const_iterator internalformat_combination_iterator;
7376 TextureViewUtilities::_compatible_internalformat_pairs internalformat_combinations =
7377 TextureViewUtilities::getLegalTextureAndViewInternalformatCombinations();
7378
7379 for (internalformat_combination_iterator = internalformat_combinations.begin();
7380 internalformat_combination_iterator != internalformat_combinations.end();
7381 internalformat_combination_iterator++)
7382 {
7383 TextureViewUtilities::_internalformat_pair internalformat_pair = *internalformat_combination_iterator;
7384 glw::GLenum texture_internalformat = internalformat_pair.first;
7385 glw::GLenum view_internalformat = internalformat_pair.second;
7386
7387 /* Initialize parent texture object storage */
7388 initTextureObject(true, /* should_init_parent_texture */
7389 texture_internalformat, view_internalformat);
7390
7391 /* Create the texture view */
7392 initTextureObject(false, /* should_init_parent_texture */
7393 texture_internalformat, view_internalformat);
7394
7395 /* Initialize buffer object storage so that it's large enough to
7396 * hold the result data.
7397 **/
7398 initBufferObject(texture_internalformat, view_internalformat);
7399
7400 /* Create the program object we'll use for the test */
7401 initProgramObject(texture_internalformat, view_internalformat);
7402
7403 /* Configure texture bindings */
7404 gl.activeTexture(m_texture_unit_for_parent_texture);
7405 GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture() call failed.");
7406
7407 gl.bindTexture(GL_TEXTURE_2D, m_to_id);
7408 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
7409
7410 gl.activeTexture(m_texture_unit_for_view_texture);
7411 GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture() call failed.");
7412
7413 gl.bindTexture(GL_TEXTURE_2D, m_view_to_id);
7414 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
7415
7416 /* Run the test program */
7417 gl.beginTransformFeedback(GL_POINTS);
7418 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
7419 {
7420 gl.drawArrays(GL_POINTS, 0 /* first */, m_texture_width * m_texture_height);
7421 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
7422 }
7423 gl.endTransformFeedback();
7424 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
7425
7426 /* Retrieve the results */
7427 const unsigned char *result_bo_data_ptr =
7428 (const unsigned char *)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
7429 const unsigned char *result_texture_data_ptr = result_bo_data_ptr;
7430 const unsigned char *result_view_data_ptr = result_bo_data_ptr + m_view_data_offset;
7431
7432 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
7433
7434 /* Verify the retrieved values are valid */
7435 verifyResultData(texture_internalformat, view_internalformat, result_texture_data_ptr, result_view_data_ptr);
7436
7437 /* Unmap the buffer object */
7438 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
7439 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
7440 } /* for (all internalformat combinations) */
7441
7442 if (m_has_test_failed)
7443 {
7444 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
7445 }
7446 else
7447 {
7448 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
7449 }
7450
7451 return STOP;
7452 }
7453
7454 /** Verifies the data XFBed out by the test's vertex shader is valid.
7455 *
7456 * @param texture_internalformat Internalformat that was used to define storage
7457 * of the parent texture object.
7458 * @param view_internalformat Internalformat that was used to define texture
7459 * view.
7460 * @param texture_data_ptr Data, as XFBed out by the vertex shader, that was
7461 * built by texelFetch() calls operating on the parent
7462 * texture object.
7463 * @param view_data_ptr Data, as XFBed out by the vertex shader, that was
7464 * built by texelFetch() calls operating on the texture
7465 * view.
7466 *
7467 **/
verifyResultData(glw::GLenum texture_internalformat,glw::GLenum view_internalformat,const unsigned char * texture_data_ptr,const unsigned char * view_data_ptr)7468 void TextureViewTestViewClasses::verifyResultData(glw::GLenum texture_internalformat, glw::GLenum view_internalformat,
7469 const unsigned char *texture_data_ptr,
7470 const unsigned char *view_data_ptr)
7471 {
7472 const char *texture_internalformat_string = TextureViewUtilities::getInternalformatString(texture_internalformat);
7473 const char *view_internalformat_string = TextureViewUtilities::getInternalformatString(view_internalformat);
7474
7475 /* For quite a number of cases, we can do a plain memcmp() applied to sampled texture/view data.
7476 * If both buffers are a match, we're OK.
7477 */
7478 bool has_failed = false;
7479 const unsigned char *mipmap_data = DE_NULL;
7480
7481 if (memcmp(texture_data_ptr, view_data_ptr, m_view_data_offset) != 0)
7482 {
7483 /* Iterate over all texel components.
7484 *
7485 * The approach we're taking here works as follows:
7486 *
7487 * 1) Calculate what values should be sampled for each component using input mipmap
7488 * data.
7489 * 2) Compare the reference values against the values returned when sampling the view.
7490 *
7491 * Note that in step 2) we're dealing with data that is returned by float/int/uint samplers,
7492 * so we need to additionally process the data that we obtain by "casting" input data to
7493 * the view's internalformat before we can perform the comparison.
7494 *
7495 * Finally, if the reference values are calculated for compressed data, we decompress it
7496 * to GL_R8/GL_RG8/GL_RGB8/GL_RGBA8 internalformat first, depending on how many components
7497 * the compressed internalformat supports.
7498 **/
7499 bool can_continue = true;
7500 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
7501
7502 /* Determine a few important properties first */
7503 const bool is_view_internalformat_compressed =
7504 TextureViewUtilities::isInternalformatCompressed(view_internalformat);
7505 unsigned int n_bits_per_view_texel = 0;
7506
7507 const unsigned int n_view_components =
7508 TextureViewUtilities::getAmountOfComponentsForInternalformat(view_internalformat);
7509 _format texture_format = TextureViewUtilities::getFormatOfInternalformat(texture_internalformat);
7510
7511 unsigned int view_component_sizes[4] = {0};
7512 _format view_format = TextureViewUtilities::getFormatOfInternalformat(view_internalformat);
7513
7514 if (!is_view_internalformat_compressed)
7515 {
7516 TextureViewUtilities::getComponentSizeForInternalformat(view_internalformat, view_component_sizes);
7517
7518 n_bits_per_view_texel =
7519 view_component_sizes[0] + view_component_sizes[1] + view_component_sizes[2] + view_component_sizes[3];
7520 }
7521 else
7522 {
7523 if (texture_internalformat == GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT ||
7524 texture_internalformat == GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT)
7525 {
7526 /* Each component of decompressed data will be retrieved as a 32-bit FP */
7527 for (unsigned int n_component = 0; n_component < n_view_components; ++n_component)
7528 {
7529 view_component_sizes[n_component] = 32 /* bits per byte */;
7530 }
7531
7532 n_bits_per_view_texel = 32 /* bits per byte */ * n_view_components;
7533 }
7534 else
7535 {
7536 /* Each component of decompressed data is stored as either signed or unsigned
7537 * byte. */
7538 for (unsigned int n_component = 0; n_component < n_view_components; ++n_component)
7539 {
7540 view_component_sizes[n_component] = 8 /* bits per byte */;
7541 }
7542
7543 n_bits_per_view_texel = 8 /* bits per byte */ * n_view_components;
7544 }
7545 }
7546
7547 /* If we need to use compressed data as reference, we need to ask GL to decompress
7548 * the mipmap data using view-specific internalformat.
7549 */
7550 mipmap_data = m_mipmap_data;
7551
7552 if (is_view_internalformat_compressed)
7553 {
7554 /* Deallocate the buffer if necessary just in case */
7555 if (m_decompressed_mipmap_data != DE_NULL)
7556 {
7557 delete[] m_decompressed_mipmap_data;
7558
7559 m_decompressed_mipmap_data = DE_NULL;
7560 }
7561
7562 m_decompressed_mipmap_data =
7563 new unsigned char[m_texture_width * m_texture_height * (n_bits_per_view_texel >> 3)];
7564
7565 glw::GLuint reference_tex_id = m_to_id;
7566 if (texture_internalformat == GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT ||
7567 texture_internalformat == GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT)
7568 {
7569 // Encodings of SIGNED and UNSIGNED BPTC compressed texture are not compatible
7570 // even though they are in the same view class. Since the "view" texture contains
7571 // the correct encoding for the results we use that as a reference instead of the
7572 // incompatible parent encoded.
7573 reference_tex_id = m_view_to_id;
7574 }
7575 gl.bindTexture(GL_TEXTURE_2D, reference_tex_id);
7576 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
7577
7578 gl.getTexImage(GL_TEXTURE_2D, 0, /* level */
7579 (n_view_components == 4) ? GL_RGBA :
7580 (n_view_components == 3) ? GL_RGB :
7581 (n_view_components == 2) ? GL_RG :
7582 GL_RED,
7583 (texture_format == FORMAT_SNORM) ? GL_BYTE :
7584 (texture_format == FORMAT_FLOAT) ? GL_FLOAT :
7585 GL_UNSIGNED_BYTE,
7586 m_decompressed_mipmap_data);
7587
7588 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexImage() call failed.");
7589
7590 mipmap_data = m_decompressed_mipmap_data;
7591 }
7592
7593 for (unsigned int n_texel = 0; n_texel < m_texture_height * m_texture_width && can_continue; ++n_texel)
7594 {
7595 /* NOTE: Vertex shader stores the sampled contents of a view texture as a
7596 * vec4/ivec4/uvec4. This means that each comonent in view_data_ptr
7597 * always takes sizeof(float) = sizeof(int) = sizeof(uint) bytes.
7598 *
7599 * NOTE: We cast input mip-map's data to view's internalformat, which is
7600 * why we're assuming each components takes n_bits_per_view_texel
7601 * bits instead of n_bits_per_mipmap_texel.
7602 */
7603 const unsigned char *mipmap_texel_data =
7604 mipmap_data + (n_bits_per_view_texel >> 3 /* 8 bits/byte */) * n_texel;
7605 float reference_components_float[4] = {0};
7606 signed int reference_components_int[4] = {0};
7607 unsigned int reference_components_uint[4] = {0};
7608 float view_components_float[4] = {0};
7609 signed int view_components_int[4] = {0};
7610 unsigned int view_components_uint[4] = {0};
7611 _sampler_type view_sampler_type =
7612 TextureViewUtilities::getSamplerTypeForInternalformat(view_internalformat);
7613 const unsigned char *view_texel_data = view_data_ptr + sizeof(float) * n_view_components * n_texel;
7614
7615 /* Retrieve data sampled from the view */
7616 for (unsigned int n_component = 0; n_component < n_view_components;
7617 view_texel_data += sizeof(float), /* as per comment */
7618 ++n_component)
7619 {
7620 switch (view_sampler_type)
7621 {
7622 case SAMPLER_TYPE_FLOAT:
7623 {
7624 view_components_float[n_component] = *((float *)view_texel_data);
7625
7626 break;
7627 }
7628
7629 case SAMPLER_TYPE_SIGNED_INTEGER:
7630 {
7631 view_components_int[n_component] = *((signed int *)view_texel_data);
7632
7633 break;
7634 }
7635
7636 case SAMPLER_TYPE_UNSIGNED_INTEGER:
7637 {
7638 view_components_uint[n_component] = *((unsigned int *)view_texel_data);
7639
7640 break;
7641 }
7642
7643 default:
7644 {
7645 TCU_FAIL("Unrecognized sampler type");
7646 }
7647 } /* switch (view_sampler_type) */
7648 } /* for (all components) */
7649
7650 /* Compute reference data. Handle non-byte aligned internalformats manually. */
7651 if (view_internalformat == GL_R11F_G11F_B10F)
7652 {
7653 const unsigned int *reference_data = (unsigned int *)mipmap_texel_data;
7654 const unsigned int red_component = (*reference_data) & ((1 << 11) - 1);
7655 const unsigned int green_component = (*reference_data >> 11) & ((1 << 11) - 1);
7656 const unsigned int blue_component = (*reference_data >> 22) & ((1 << 10) - 1);
7657
7658 if (view_sampler_type == SAMPLER_TYPE_FLOAT)
7659 {
7660 reference_components_float[0] = Float11(red_component).asFloat();
7661 reference_components_float[1] = Float11(green_component).asFloat();
7662 reference_components_float[2] = Float10(blue_component).asFloat();
7663 }
7664 else
7665 {
7666 TCU_FAIL("Internal error: invalid sampler type requested");
7667 }
7668 }
7669 else if (view_internalformat == GL_RGB9_E5)
7670 {
7671 /* Refactored version of tcuTexture.cpp::unpackRGB999E5() */
7672 const unsigned int *reference_data = (unsigned int *)mipmap_texel_data;
7673 const unsigned int exponent = (*reference_data >> 27) & ((1 << 5) - 1);
7674 const unsigned int red_component = (*reference_data) & ((1 << 9) - 1);
7675 const unsigned int green_component = (*reference_data >> 9) & ((1 << 9) - 1);
7676 const unsigned int blue_component = (*reference_data >> 18) & ((1 << 9) - 1);
7677
7678 float shared_exponent =
7679 deFloatPow(2.0f, (float)((int)exponent - 15 /* exponent bias */ - 9 /* mantissa */));
7680
7681 if (view_sampler_type == SAMPLER_TYPE_FLOAT)
7682 {
7683 reference_components_float[0] = float(red_component) * shared_exponent;
7684 reference_components_float[1] = float(green_component) * shared_exponent;
7685 reference_components_float[2] = float(blue_component) * shared_exponent;
7686 }
7687 else
7688 {
7689 TCU_FAIL("Internal error: invalid sampler type requested");
7690 }
7691 }
7692 else if (view_internalformat == GL_RGB10_A2)
7693 {
7694 unsigned int *reference_data = (unsigned int *)mipmap_texel_data;
7695 const unsigned int mask_rgb = (1 << 10) - 1;
7696 const unsigned int mask_a = (1 << 2) - 1;
7697
7698 if (view_sampler_type == SAMPLER_TYPE_FLOAT)
7699 {
7700 reference_components_float[0] = float(((*reference_data)) & (mask_rgb)) / float(mask_rgb);
7701 reference_components_float[1] = float(((*reference_data) >> 10) & (mask_rgb)) / float(mask_rgb);
7702 reference_components_float[2] = float(((*reference_data) >> 20) & (mask_rgb)) / float(mask_rgb);
7703 reference_components_float[3] = float(((*reference_data) >> 30) & (mask_a)) / float(mask_a);
7704 }
7705 else
7706 {
7707 TCU_FAIL("Internal error: invalid sampler type requested");
7708 }
7709 }
7710 else if (view_internalformat == GL_RGB10_A2UI)
7711 {
7712 unsigned int *reference_data = (unsigned int *)mipmap_texel_data;
7713 const unsigned int mask_rgb = (1 << 10) - 1;
7714 const unsigned int mask_a = (1 << 2) - 1;
7715
7716 if (view_sampler_type == SAMPLER_TYPE_UNSIGNED_INTEGER)
7717 {
7718 reference_components_uint[0] = ((*reference_data)) & (mask_rgb);
7719 reference_components_uint[1] = ((*reference_data) >> 10) & (mask_rgb);
7720 reference_components_uint[2] = ((*reference_data) >> 20) & (mask_rgb);
7721 reference_components_uint[3] = ((*reference_data) >> 30) & (mask_a);
7722 }
7723 else
7724 {
7725 TCU_FAIL("Internal error: invalid sampler type requested");
7726 }
7727 }
7728 else if (view_internalformat == GL_RG16F)
7729 {
7730 unsigned short *reference_data = (unsigned short *)mipmap_texel_data;
7731
7732 if (view_sampler_type == SAMPLER_TYPE_FLOAT)
7733 {
7734 reference_components_float[0] = tcu::Float16(*(reference_data + 0)).asFloat();
7735 reference_components_float[1] = tcu::Float16(*(reference_data + 1)).asFloat();
7736 }
7737 else
7738 {
7739 TCU_FAIL("Internal error: invalid sampler type requested");
7740 }
7741 }
7742 else
7743 {
7744 void *result_data = NULL;
7745
7746 switch (view_sampler_type)
7747 {
7748 case SAMPLER_TYPE_FLOAT:
7749 result_data = reference_components_float;
7750 break;
7751 case SAMPLER_TYPE_SIGNED_INTEGER:
7752 result_data = reference_components_int;
7753 break;
7754 case SAMPLER_TYPE_UNSIGNED_INTEGER:
7755 result_data = reference_components_uint;
7756 break;
7757
7758 default:
7759 TCU_FAIL("Unrecognized sampler type");
7760 }
7761
7762 getComponentDataForByteAlignedInternalformat(mipmap_texel_data, n_view_components, view_component_sizes,
7763 view_format, result_data);
7764 }
7765
7766 for (unsigned int n_component = 0; n_component < n_view_components; ++n_component)
7767 {
7768 /* If view texture operates on sRGB color space, we need to adjust our
7769 * reference value so that it is moved back into linear space.
7770 */
7771 if (TextureViewUtilities::isInternalformatSRGB(view_internalformat) &&
7772 !TextureViewUtilities::isInternalformatSRGB(texture_internalformat))
7773 {
7774 DE_ASSERT(view_sampler_type == SAMPLER_TYPE_FLOAT);
7775
7776 /* Convert as per (8.14) from GL4.4 spec. Exclude alpha channel. */
7777 if (n_component != 3)
7778 {
7779 if (reference_components_float[n_component] <= 0.04045f)
7780 {
7781 reference_components_float[n_component] /= 12.92f;
7782 }
7783 else
7784 {
7785 reference_components_float[n_component] =
7786 deFloatPow((reference_components_float[n_component] + 0.055f) / 1.055f, 2.4f);
7787 }
7788 } /* if (n_component != 3) */
7789 } /* if (TextureViewUtilities::isInternalformatSRGB(view_internalformat) ) */
7790
7791 /* Compare the reference and view texture values */
7792 const float epsilon_float = 1.0f / float((1 << (view_component_sizes[n_component] - 1)) - 1);
7793 const signed int epsilon_int = 1;
7794 const unsigned int epsilon_uint = 1;
7795
7796 switch (view_sampler_type)
7797 {
7798 case SAMPLER_TYPE_FLOAT:
7799 {
7800 if (de::abs(reference_components_float[n_component] - view_components_float[n_component]) >
7801 epsilon_float)
7802 {
7803 has_failed = true;
7804 }
7805
7806 break;
7807 }
7808
7809 case SAMPLER_TYPE_SIGNED_INTEGER:
7810 {
7811 signed int larger_value = 0;
7812 signed int smaller_value = 0;
7813
7814 if (reference_components_int[n_component] > view_components_int[n_component])
7815 {
7816 larger_value = reference_components_int[n_component];
7817 smaller_value = view_components_int[n_component];
7818 }
7819 else
7820 {
7821 smaller_value = reference_components_int[n_component];
7822 larger_value = view_components_int[n_component];
7823 }
7824
7825 if ((larger_value - smaller_value) > epsilon_int)
7826 {
7827 has_failed = true;
7828 }
7829
7830 break;
7831 }
7832
7833 case SAMPLER_TYPE_UNSIGNED_INTEGER:
7834 {
7835 unsigned int larger_value = 0;
7836 unsigned int smaller_value = 0;
7837
7838 if (reference_components_uint[n_component] > view_components_uint[n_component])
7839 {
7840 larger_value = reference_components_uint[n_component];
7841 smaller_value = view_components_uint[n_component];
7842 }
7843 else
7844 {
7845 smaller_value = reference_components_uint[n_component];
7846 larger_value = view_components_uint[n_component];
7847 }
7848
7849 if ((larger_value - smaller_value) > epsilon_uint)
7850 {
7851 has_failed = true;
7852 }
7853
7854 break;
7855 }
7856
7857 default:
7858 TCU_FAIL("Unrecognized sampler type");
7859 } /* switch (view_sampler_type) */
7860
7861 if (has_failed)
7862 {
7863 can_continue = false;
7864
7865 switch (view_sampler_type)
7866 {
7867 case SAMPLER_TYPE_FLOAT:
7868 {
7869 m_testCtx.getLog()
7870 << tcu::TestLog::Message
7871 << "Invalid data sampled from a texture view "
7872 "["
7873 << view_internalformat_string
7874 << "]"
7875 " created from a texture object"
7876 "["
7877 << texture_internalformat_string
7878 << "]"
7879 " at texel "
7880 "("
7881 << (n_texel % m_texture_width) << ", " << (n_texel / m_texture_height) << "): expected:("
7882 << reference_components_float[0] << ", " << reference_components_float[1] << ", "
7883 << reference_components_float[2] << ", " << reference_components_float[3] << ") found:("
7884 << view_components_float[0] << ", " << view_components_float[1] << ", "
7885 << view_components_float[2] << ", " << view_components_float[3] << ")."
7886 << tcu::TestLog::EndMessage;
7887
7888 break;
7889 }
7890
7891 case SAMPLER_TYPE_SIGNED_INTEGER:
7892 {
7893 m_testCtx.getLog() << tcu::TestLog::Message
7894 << "Invalid data sampled from a signed integer texture view "
7895 "["
7896 << view_internalformat_string
7897 << "]"
7898 " created from a texture object"
7899 "["
7900 << texture_internalformat_string
7901 << "]"
7902 " at texel "
7903 "("
7904 << (n_texel % m_texture_width) << ", " << (n_texel / m_texture_height)
7905 << "): expected:(" << reference_components_int[0] << ", "
7906 << reference_components_int[1] << ", " << reference_components_int[2] << ", "
7907 << reference_components_int[3] << ") found:(" << view_components_int[0]
7908 << ", " << view_components_int[1] << ", " << view_components_int[2] << ", "
7909 << view_components_int[3] << ")." << tcu::TestLog::EndMessage;
7910
7911 break;
7912 }
7913
7914 case SAMPLER_TYPE_UNSIGNED_INTEGER:
7915 {
7916 m_testCtx.getLog()
7917 << tcu::TestLog::Message
7918 << "Invalid data sampled from an unsigned integer texture view "
7919 "["
7920 << view_internalformat_string
7921 << "]"
7922 " created from a texture object"
7923 "["
7924 << texture_internalformat_string
7925 << "]"
7926 " at texel "
7927 "("
7928 << (n_texel % m_texture_width) << ", " << (n_texel / m_texture_height) << "): expected:("
7929 << reference_components_uint[0] << ", " << reference_components_uint[1] << ", "
7930 << reference_components_uint[2] << ", " << reference_components_uint[3] << ") found:("
7931 << view_components_uint[0] << ", " << view_components_uint[1] << ", "
7932 << view_components_uint[2] << ", " << view_components_uint[3] << ")."
7933 << tcu::TestLog::EndMessage;
7934
7935 break;
7936 }
7937
7938 default:
7939 TCU_FAIL("Unrecognized sampler type");
7940 } /* switch (view_sampler_type) */
7941
7942 break;
7943 } /* if (has_failed) */
7944 } /* for (all components) */
7945 } /* for (all texels) */
7946 } /* if (memcmp(texture_data_ptr, view_data_ptr, m_view_data_offset) != 0) */
7947
7948 if (has_failed)
7949 {
7950 /* Log detailed information about the failure */
7951 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid data read from a view of internalformat "
7952 << "[" << view_internalformat_string << "]"
7953 << " created from a texture of internalformat "
7954 << "[" << texture_internalformat_string << "]"
7955 << ". Byte streams follow:" << tcu::TestLog::EndMessage;
7956
7957 /* Form texture and view data strings */
7958 std::stringstream mipmap_data_sstream;
7959 std::stringstream sampled_view_data_sstream;
7960
7961 mipmap_data_sstream.fill('0');
7962 sampled_view_data_sstream.fill('0');
7963
7964 mipmap_data_sstream.width(2);
7965 sampled_view_data_sstream.width(2);
7966
7967 mipmap_data_sstream << "Mip-map data: [";
7968 sampled_view_data_sstream << "Sampled view data: [";
7969
7970 for (unsigned int n = 0; n < m_view_data_offset; ++n)
7971 {
7972 mipmap_data_sstream << "0x" << std::hex << (int)(mipmap_data[n]);
7973 sampled_view_data_sstream << "0x" << std::hex << (int)(view_data_ptr[n]);
7974
7975 if (n != (m_view_data_offset - 1))
7976 {
7977 mipmap_data_sstream << "|";
7978 sampled_view_data_sstream << "|";
7979 }
7980 else
7981 {
7982 mipmap_data_sstream << "]";
7983 sampled_view_data_sstream << "]";
7984 }
7985 }
7986
7987 sampled_view_data_sstream << "\n";
7988 mipmap_data_sstream << "\n";
7989
7990 /* Log both strings */
7991 m_testCtx.getLog() << tcu::TestLog::Message << mipmap_data_sstream.str() << sampled_view_data_sstream.str()
7992 << tcu::TestLog::EndMessage;
7993
7994 /* Do not fail the test at this point. Instead, raise a failure flag that will
7995 * cause the test to fail once all iterations execute */
7996 m_has_test_failed = true;
7997 }
7998 else
7999 {
8000 m_testCtx.getLog() << tcu::TestLog::Message << "Correct data read from a view of internalformat "
8001 << "[" << view_internalformat_string << "]"
8002 << " created from a texture of internalformat "
8003 << "[" << texture_internalformat_string << "]" << tcu::TestLog::EndMessage;
8004 }
8005 }
8006
8007 /** Constructor.
8008 *
8009 * @param context Rendering context.
8010 *
8011 **/
TextureViewTestCoherency(deqp::Context & context)8012 TextureViewTestCoherency::TextureViewTestCoherency(deqp::Context &context)
8013 : TestCase(context, "coherency", "Verifies view/parent texture coherency")
8014 , m_are_images_supported(false)
8015 , m_bo_id(0)
8016 , m_draw_fbo_id(0)
8017 , m_gradient_verification_po_id(0)
8018 , m_gradient_verification_po_sample_exact_uv_location(-1)
8019 , m_gradient_verification_po_lod_location(-1)
8020 , m_gradient_verification_po_texture_location(-1)
8021 , m_gradient_verification_vs_id(0)
8022 , m_gradient_image_write_image_size_location(-1)
8023 , m_gradient_image_write_po_id(0)
8024 , m_gradient_image_write_vs_id(0)
8025 , m_gradient_write_po_id(0)
8026 , m_gradient_write_fs_id(0)
8027 , m_gradient_write_vs_id(0)
8028 , m_read_fbo_id(0)
8029 , m_static_to_id(0)
8030 , m_to_id(0)
8031 , m_vao_id(0)
8032 , m_view_to_id(0)
8033 , m_verification_po_expected_color_location(-1)
8034 , m_verification_po_lod_location(-1)
8035 , m_verification_po_id(0)
8036 , m_verification_vs_id(0)
8037 , m_static_texture_height(1)
8038 , m_static_texture_width(1)
8039 , m_texture_height(64)
8040 , m_texture_n_components(4)
8041 , m_texture_n_levels(7)
8042 , m_texture_width(64)
8043 {
8044 /* Initialize static color that will be used for some of the cases */
8045 m_static_color_byte[0] = 100;
8046 m_static_color_byte[1] = 0;
8047 m_static_color_byte[2] = 255;
8048 m_static_color_byte[3] = 200;
8049
8050 m_static_color_float[0] = float(m_static_color_byte[0]) / 255.0f;
8051 m_static_color_float[1] = float(m_static_color_byte[1]) / 255.0f;
8052 m_static_color_float[2] = float(m_static_color_byte[2]) / 255.0f;
8053 m_static_color_float[3] = float(m_static_color_byte[3]) / 255.0f;
8054 }
8055
8056 /** Verifies that texture/view & view/texture coherency requirement is met
8057 * when glTexSubImage2D() or glBlitFramebuffer() API calls are used to modify
8058 * the contents of one of the mip-maps. The function does not use any memory
8059 * barriers as these are not required for the objects to stay synchronised.
8060 *
8061 * Throws TestError exceptionif the GL implementation fails the check.
8062 *
8063 * @param texture_type Defines whether it should be parent texture or
8064 * its view that the writing operation should be
8065 * performed against. The reading operation will
8066 * be issued against the sibling object.
8067 * @param should_use_glTexSubImage2D true if glTexSubImage2D() should be used for the
8068 * check, false to use glBlitFramebuffer().
8069 *
8070 **/
checkAPICallCoherency(_texture_type texture_type,bool should_use_glTexSubImage2D)8071 void TextureViewTestCoherency::checkAPICallCoherency(_texture_type texture_type, bool should_use_glTexSubImage2D)
8072 {
8073 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
8074 unsigned int write_to_height = 0;
8075 unsigned int write_to_width = 0;
8076 glw::GLuint write_to_id = 0;
8077
8078 getWritePropertiesForTextureType(texture_type, &write_to_id, &write_to_width, &write_to_height);
8079
8080 if (should_use_glTexSubImage2D)
8081 {
8082 /* Update texture binding for texture unit 0, given the texture type the caller wants
8083 * us to test. We'll need the binding set appropriately for the subsequent
8084 * glTexSubImage2D() call.
8085 */
8086 gl.activeTexture(GL_TEXTURE0);
8087 GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture() call failed.");
8088
8089 gl.bindTexture(GL_TEXTURE_2D, write_to_id);
8090 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
8091 }
8092 else
8093 {
8094 /* To perform a blit operation, we need to configure draw & read FBO, taking
8095 * the tested texture type into account. */
8096 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_draw_fbo_id);
8097 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_read_fbo_id);
8098 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call(s) failed.");
8099
8100 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, write_to_id, 1); /* level */
8101 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed for GL_DRAW_FRAMEBUFFER target.");
8102
8103 gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_static_to_id,
8104 0); /* level */
8105 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed for GL_READ_FRAMEBUFFER target.");
8106 }
8107
8108 /* Execute the API call */
8109 const unsigned int region_width = (write_to_width >> 1);
8110 const unsigned int region_height = (write_to_height >> 1);
8111 const unsigned int region_x = region_width - (region_width >> 1);
8112 const unsigned int region_y = region_height - (region_height >> 1);
8113
8114 if (should_use_glTexSubImage2D)
8115 {
8116 /* Call glTexSubImage2D() to replace a portion of the gradient with a static color */
8117 {
8118 unsigned char *static_color_data_ptr = getStaticColorTextureData(region_width, region_height);
8119
8120 gl.texSubImage2D(GL_TEXTURE_2D, 1, /* level */
8121 region_x, region_y, region_width, region_height, GL_RGBA, GL_UNSIGNED_BYTE,
8122 static_color_data_ptr);
8123
8124 /* Good to release static color data buffer at this point */
8125 delete[] static_color_data_ptr;
8126
8127 static_color_data_ptr = DE_NULL;
8128
8129 /* Make sure the API call was successful */
8130 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexSubImage2D() call failed.");
8131 }
8132 }
8133 else
8134 {
8135 gl.blitFramebuffer(0, /* srcX0 */
8136 0, /* srcY0 */
8137 m_static_texture_width, /* srcX1 */
8138 m_static_texture_height, /* srcY1 */
8139 region_x, region_y, region_x + region_width, region_y + region_height, GL_COLOR_BUFFER_BIT,
8140 GL_NEAREST);
8141 GLU_EXPECT_NO_ERROR(gl.getError(), "glBlitFramebuffer() call failed.");
8142 }
8143
8144 /* Bind the sibling object so that we can make sure the data read from the
8145 * region can be correctly read from a shader without a memory barrier.
8146 *
8147 * While we're here, also determine which LOD we should be sampling from in
8148 * the shader.
8149 **/
8150 unsigned int read_lod = 0;
8151 glw::GLuint read_to_id = 0;
8152
8153 getReadPropertiesForTextureType(texture_type, &read_to_id, &read_lod);
8154
8155 gl.bindTexture(GL_TEXTURE_2D, read_to_id);
8156 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
8157
8158 /* Update the test program uniforms before we carry on with actual
8159 * verification
8160 */
8161 gl.useProgram(m_verification_po_id);
8162 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
8163
8164 DE_STATIC_ASSERT(sizeof(m_static_color_float) == sizeof(float) * 4);
8165
8166 gl.uniform4fv(m_verification_po_expected_color_location, 1, /* count */
8167 m_static_color_float);
8168 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4fv() call failed.");
8169
8170 gl.uniform1i(m_verification_po_lod_location, read_lod);
8171 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i() call failed.");
8172
8173 /* Make sure rasterization is disabled before we carry on */
8174 gl.enable(GL_RASTERIZER_DISCARD);
8175 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable() call failed.");
8176
8177 /* Go ahead with the rendering. Make sure to capture the varyings */
8178 gl.beginTransformFeedback(GL_POINTS);
8179 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
8180 {
8181 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
8182 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
8183 }
8184 gl.endTransformFeedback();
8185 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
8186
8187 /* Map the buffer object so we can validate the sampling result */
8188 const glw::GLint *data_ptr = (const glw::GLint *)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
8189
8190 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
8191 DE_ASSERT(data_ptr != NULL);
8192
8193 /* Verify the outcome of the sampling operation */
8194 if (*data_ptr != 1)
8195 {
8196 TCU_FAIL("Invalid data was sampled in vertex shader");
8197 }
8198
8199 /* Unmap the buffer object */
8200 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
8201 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
8202
8203 data_ptr = DE_NULL;
8204
8205 /* Disable GL_RASTERIZER_DISCARD mode */
8206 gl.disable(GL_RASTERIZER_DISCARD);
8207 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() call failed.");
8208 }
8209
8210 /** Verifies texture/view & view/texture coherency is met when one of the objects
8211 * is used as a render-target. The function writes to user-specified texture type,
8212 * and then verifies the contents of the sibling object.
8213 *
8214 * The function throws TestError exception if any of the checks fail.
8215 *
8216 * @param texture_type Tells which of the two objects should be written to.
8217 * @param should_use_images true if images should be used for
8218 * @param barrier_type Type of the memory barrier that should be injected
8219 * after vertex shader stage with image writes is executed.
8220 * Must be BARRIER_TYPE_NONE if @param should_use_images
8221 * is set to false.
8222 * @param verification_mean Determines whether the verification should be performed
8223 * using a program object, or by CPU with the data
8224 * extracted from the sibling object using a glGetTexImage()
8225 * call.
8226 *
8227 **/
checkProgramWriteCoherency(_texture_type texture_type,bool should_use_images,_barrier_type barrier_type,_verification_mean verification_mean)8228 void TextureViewTestCoherency::checkProgramWriteCoherency(_texture_type texture_type, bool should_use_images,
8229 _barrier_type barrier_type,
8230 _verification_mean verification_mean)
8231 {
8232 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
8233
8234 if (!should_use_images)
8235 {
8236 /* Quick check: no barrier should be requested if images are not used */
8237 DE_ASSERT(barrier_type == BARRIER_TYPE_NONE);
8238
8239 /* Quick check: glGetTexImage*() call should only be used for verification
8240 * when images are used */
8241 DE_ASSERT(verification_mean == VERIFICATION_MEAN_PROGRAM);
8242 }
8243
8244 /* Determine GL id of an object we will be rendering the gradient to */
8245 glw::GLuint write_to_id = 0;
8246 unsigned int write_to_width = 0;
8247 unsigned int write_to_height = 0;
8248
8249 getWritePropertiesForTextureType(texture_type, &write_to_id, &write_to_width, &write_to_height);
8250
8251 /* Configure the render targets */
8252 if (should_use_images)
8253 {
8254 gl.bindImageTexture(0, /* unit */
8255 write_to_id, 1, /* second level */
8256 GL_FALSE, /* layered */
8257 0, /* layer */
8258 GL_WRITE_ONLY, GL_RGBA8);
8259
8260 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture() call failed.");
8261 }
8262 else
8263 {
8264 /* We first need to fill either the texture or its sibling view with
8265 * gradient data. Set up draw framebuffer */
8266 gl.bindFramebuffer(GL_FRAMEBUFFER, m_draw_fbo_id);
8267 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed for GL_FRAMEBUFFER target");
8268
8269 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, write_to_id, 1); /* level */
8270 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
8271
8272 /* Configure the viewport accordingly */
8273 gl.viewport(0, /* x */
8274 0, /* y */
8275 write_to_width, write_to_height);
8276 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed.");
8277 }
8278
8279 /* The gradient needs to be rendered differently, depending on whether
8280 * we're asked to use images or not */
8281 if (should_use_images)
8282 {
8283 gl.useProgram(m_gradient_image_write_po_id);
8284 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
8285
8286 gl.uniform2i(m_gradient_image_write_image_size_location, write_to_width, write_to_height);
8287 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform2i() call failed.");
8288
8289 gl.enable(GL_RASTERIZER_DISCARD);
8290 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_RASTERIZER_DISCARD) call failed.");
8291 {
8292 gl.drawArrays(GL_POINTS, 0 /* first */, write_to_width * write_to_height);
8293 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
8294 }
8295 gl.disable(GL_RASTERIZER_DISCARD);
8296 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable(GL_RASTERIZER_DISCARD) call failed.");
8297
8298 /* If the caller requested any barriers, issue them at this point */
8299 switch (barrier_type)
8300 {
8301 case BARRIER_TYPE_TEXTURE_FETCH_BARRIER_BIT:
8302 {
8303 gl.memoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
8304
8305 GLU_EXPECT_NO_ERROR(gl.getError(),
8306 "glMemoryBarrier() call failed for GL_TEXTURE_FETCH_BARRIER_BIT barrier");
8307
8308 break;
8309 }
8310
8311 case BARRIER_TYPE_TEXTURE_UPDATE_BUFFER_BIT:
8312 {
8313 gl.memoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
8314
8315 GLU_EXPECT_NO_ERROR(gl.getError(),
8316 "glMemoryBarrier() call failed for GL_TEXTURE_UPDATE_BARRIER_BIT barrier");
8317
8318 break;
8319 }
8320
8321 default:
8322 {
8323 TCU_FAIL("Unrecognized barrier type");
8324 }
8325 } /* switch (barrier_type) */
8326 } /* if (should_use_images) */
8327 else
8328 {
8329 /* Render the gradient on a full-screen quad */
8330 gl.useProgram(m_gradient_write_po_id);
8331 GLU_EXPECT_NO_ERROR(gl.getError(), "gluseProgram() call failed.");
8332
8333 gl.drawArrays(GL_TRIANGLE_STRIP, 0 /* first */, 4 /* count */);
8334 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
8335
8336 gl.textureBarrier();
8337 }
8338
8339 /* Determine which texture and which mip-map level we will need to sample
8340 * in order to verify whether the former operations have been completed
8341 * successfully.
8342 **/
8343 unsigned int read_lod = 0;
8344 glw::GLuint read_to_id = 0;
8345
8346 getReadPropertiesForTextureType(texture_type, &read_to_id, &read_lod);
8347
8348 /* Before we proceed with verification, update the texture binding so that
8349 * the verification program can sample from the right texture */
8350 gl.activeTexture(GL_TEXTURE0);
8351 GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture() call failed.");
8352
8353 gl.bindTexture(GL_TEXTURE_2D, read_to_id);
8354 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
8355
8356 if (verification_mean == VERIFICATION_MEAN_PROGRAM)
8357 {
8358 /* Switch to a verification program. It uses a vertex shader to sample
8359 * all texels of the texture so issue as many invocations as necessary. */
8360 unsigned int n_invocations = write_to_width * write_to_height;
8361
8362 gl.useProgram(m_gradient_verification_po_id);
8363 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
8364
8365 gl.uniform1i(m_gradient_verification_po_texture_location, 0);
8366 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i() call failed.");
8367
8368 gl.uniform1i(m_gradient_verification_po_sample_exact_uv_location, should_use_images);
8369 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i() call failed.");
8370
8371 gl.uniform1f(m_gradient_verification_po_lod_location, (float)read_lod);
8372 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1f() call failed.");
8373
8374 gl.enable(GL_RASTERIZER_DISCARD);
8375 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_RASTERIZER_DISCARD) call failed.");
8376
8377 gl.beginTransformFeedback(GL_POINTS);
8378 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
8379 {
8380 gl.drawArrays(GL_POINTS, 0 /* first */, n_invocations);
8381 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
8382 }
8383 gl.endTransformFeedback();
8384 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
8385
8386 gl.disable(GL_RASTERIZER_DISCARD);
8387 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable(GL_RASTERIZER_DISCARD) call failed.");
8388
8389 /* Map the result buffer object storage into process space */
8390 const int *result_data_ptr = (const int *)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
8391
8392 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
8393
8394 if (result_data_ptr == DE_NULL)
8395 {
8396 TCU_FAIL("glMapBuffer() did not generate an error but returned a NULL pointer");
8397 }
8398
8399 /* Verify the XFBed data */
8400 for (unsigned int n_invocation = 0; n_invocation < n_invocations; ++n_invocation)
8401 {
8402 if (result_data_ptr[n_invocation] != 1)
8403 {
8404 unsigned int invocation_x = n_invocation % write_to_width;
8405 unsigned int invocation_y = n_invocation / write_to_width;
8406
8407 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid data was sampled at "
8408 << "(" << invocation_x << ", " << invocation_y << ") when sampling from "
8409 << ((texture_type == TEXTURE_TYPE_PARENT_TEXTURE) ? "a texture" : "a view")
8410 << tcu::TestLog::EndMessage;
8411
8412 /* Make sure the buffer is unmapped before throwing the exception */
8413 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
8414
8415 TCU_FAIL("Invalid data sampled");
8416 }
8417 } /* for (all invocations) */
8418
8419 /* Unmap the buffer storage */
8420 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
8421 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
8422 } /* if (verification_mean == VERIFICATION_MEAN_PROGRAM) */
8423 else
8424 {
8425 DE_ASSERT(verification_mean == VERIFICATION_MEAN_GLGETTEXIMAGE);
8426
8427 /* Allocate space for the data */
8428 unsigned char *data_ptr = new unsigned char[write_to_width * write_to_height * m_texture_n_components];
8429
8430 /* Retrieve the rendered data */
8431 gl.getTexImage(GL_TEXTURE_2D, read_lod, GL_RGBA, GL_UNSIGNED_BYTE, data_ptr);
8432
8433 if (gl.getError() != GL_NO_ERROR)
8434 {
8435 /* Release the buffer before we throw an exception */
8436 delete[] data_ptr;
8437
8438 TCU_FAIL("glGetTexImage() call failed.");
8439 }
8440
8441 /* Verify the data is correct */
8442 const int epsilon = 1;
8443 bool is_data_correct = true;
8444
8445 for (unsigned int y = 0; y < write_to_height; ++y)
8446 {
8447 const unsigned char *row_ptr = data_ptr + y * m_texture_n_components * write_to_width;
8448
8449 for (unsigned int x = 0; x < write_to_width; ++x)
8450 {
8451 const unsigned char *texel_ptr = row_ptr + x * m_texture_n_components;
8452 const float end_rgba[] = {0.0f, 0.1f, 1.0f, 1.0f};
8453 const float lerp_factor = float(x) / float(write_to_width);
8454 const float start_rgba[] = {1.0f, 0.9f, 0.0f, 0.0f};
8455 const float expected_data_float[] = {start_rgba[0] * (1.0f - lerp_factor) + end_rgba[0] * lerp_factor,
8456 start_rgba[1] * (1.0f - lerp_factor) + end_rgba[1] * lerp_factor,
8457 start_rgba[2] * (1.0f - lerp_factor) + end_rgba[2] * lerp_factor,
8458 start_rgba[3] * (1.0f - lerp_factor) + end_rgba[3] * lerp_factor};
8459 const unsigned char expected_data_ubyte[] = {
8460 (unsigned char)(expected_data_float[0] * 255.0f), (unsigned char)(expected_data_float[1] * 255.0f),
8461 (unsigned char)(expected_data_float[2] * 255.0f), (unsigned char)(expected_data_float[3] * 255.0f)};
8462
8463 if (de::abs((int)texel_ptr[0] - (int)expected_data_ubyte[0]) > epsilon ||
8464 de::abs((int)texel_ptr[1] - (int)expected_data_ubyte[1]) > epsilon ||
8465 de::abs((int)texel_ptr[2] - (int)expected_data_ubyte[2]) > epsilon ||
8466 de::abs((int)texel_ptr[3] - (int)expected_data_ubyte[3]) > epsilon)
8467 {
8468 is_data_correct = false;
8469
8470 break;
8471 }
8472 }
8473 } /* for (all rows) */
8474
8475 /* Good to release the data buffer at this point */
8476 delete[] data_ptr;
8477
8478 data_ptr = DE_NULL;
8479
8480 /* Fail the test if any of the rendered texels were found invalid */
8481 if (!is_data_correct)
8482 {
8483 TCU_FAIL("Invalid data sampled");
8484 }
8485 }
8486 }
8487
8488 /** Deinitializes all GL objects that may have been created during
8489 * test execution.
8490 **/
deinit()8491 void TextureViewTestCoherency::deinit()
8492 {
8493 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
8494
8495 /* Release any GL objects the test may have created */
8496 if (m_bo_id != 0)
8497 {
8498 gl.deleteBuffers(1, &m_bo_id);
8499
8500 m_bo_id = 0;
8501 }
8502
8503 if (m_draw_fbo_id != 0)
8504 {
8505 gl.deleteFramebuffers(1, &m_draw_fbo_id);
8506
8507 m_draw_fbo_id = 0;
8508 }
8509
8510 if (m_gradient_image_write_po_id != 0)
8511 {
8512 gl.deleteProgram(m_gradient_image_write_po_id);
8513
8514 m_gradient_image_write_po_id = 0;
8515 }
8516
8517 if (m_gradient_image_write_vs_id != 0)
8518 {
8519 gl.deleteShader(m_gradient_image_write_vs_id);
8520
8521 m_gradient_image_write_vs_id = 0;
8522 }
8523
8524 if (m_gradient_verification_po_id != 0)
8525 {
8526 gl.deleteProgram(m_gradient_verification_po_id);
8527
8528 m_gradient_verification_po_id = 0;
8529 }
8530
8531 if (m_gradient_verification_vs_id != 0)
8532 {
8533 gl.deleteShader(m_gradient_verification_vs_id);
8534
8535 m_gradient_verification_vs_id = 0;
8536 }
8537
8538 if (m_gradient_write_fs_id != 0)
8539 {
8540 gl.deleteShader(m_gradient_write_fs_id);
8541
8542 m_gradient_write_fs_id = 0;
8543 }
8544
8545 if (m_gradient_write_po_id != 0)
8546 {
8547 gl.deleteProgram(m_gradient_write_po_id);
8548
8549 m_gradient_write_po_id = 0;
8550 }
8551
8552 if (m_gradient_write_vs_id != 0)
8553 {
8554 gl.deleteShader(m_gradient_write_vs_id);
8555
8556 m_gradient_write_vs_id = 0;
8557 }
8558
8559 if (m_read_fbo_id != 0)
8560 {
8561 gl.deleteFramebuffers(1, &m_read_fbo_id);
8562
8563 m_read_fbo_id = 0;
8564 }
8565
8566 if (m_static_to_id != 0)
8567 {
8568 gl.deleteTextures(1, &m_static_to_id);
8569
8570 m_static_to_id = 0;
8571 }
8572
8573 if (m_to_id != 0)
8574 {
8575 gl.deleteTextures(1, &m_to_id);
8576
8577 m_to_id = 0;
8578 }
8579
8580 if (m_vao_id != 0)
8581 {
8582 gl.deleteVertexArrays(1, &m_vao_id);
8583
8584 m_vao_id = 0;
8585 }
8586
8587 if (m_view_to_id != 0)
8588 {
8589 gl.deleteTextures(1, &m_view_to_id);
8590
8591 m_view_to_id = 0;
8592 }
8593
8594 if (m_verification_po_id != 0)
8595 {
8596 gl.deleteProgram(m_verification_po_id);
8597
8598 m_verification_po_id = 0;
8599 }
8600
8601 if (m_verification_vs_id != 0)
8602 {
8603 gl.deleteShader(m_verification_vs_id);
8604
8605 m_verification_vs_id = 0;
8606 }
8607
8608 /* Disable GL_RASTERIZER_DISCARD mode */
8609 gl.disable(GL_RASTERIZER_DISCARD);
8610 }
8611
8612 /** Allocates a sufficiently large buffer for RGBA8 data and fills it with
8613 * a horizontal gradient (as described in the test specification)
8614 *
8615 * It is user's responsibility to release the buffer when no longer needed.
8616 *
8617 * @return Pointer to the buffer.
8618 **/
getHorizontalGradientData() const8619 unsigned char *TextureViewTestCoherency::getHorizontalGradientData() const
8620 {
8621 const float end_rgba[] = {1.0f, 0.9f, 0.0f, 0.0f};
8622 unsigned char *result = new unsigned char[m_texture_width * m_texture_height * m_texture_n_components];
8623 const float start_rgba[] = {0.0f, 0.1f, 1.0f, 1.0f};
8624 const unsigned int texel_size = m_texture_n_components;
8625
8626 for (unsigned int y = 0; y < m_texture_height; ++y)
8627 {
8628 unsigned char *row_data_ptr = result + texel_size * m_texture_width * y;
8629
8630 for (unsigned int x = 0; x < m_texture_width; ++x)
8631 {
8632 const float lerp_factor = float(x) / float(m_texture_width);
8633 unsigned char *pixel_data_ptr = row_data_ptr + texel_size * x;
8634
8635 for (unsigned int n_component = 0; n_component < 4 /* rgba */; ++n_component)
8636 {
8637 pixel_data_ptr[n_component] = (unsigned char)((end_rgba[n_component] * lerp_factor +
8638 start_rgba[n_component] * (1.0f - lerp_factor)) *
8639 255.0f);
8640 } /* for (all components) */
8641 } /* for (all columns) */
8642 } /* for (all rows) */
8643
8644 return result;
8645 }
8646
8647 /** Retrieves properties of a sibling object that should be read from during
8648 * some of the checks.
8649 *
8650 * @param texture_type Type of the texture object that should be used for reading.
8651 * @param out_to_id Deref will be used to store texture object ID of the object.
8652 * @param out_read_lod Deref will be used to store LOD to be used for reading from
8653 * the object.
8654 *
8655 **/
getReadPropertiesForTextureType(_texture_type texture_type,glw::GLuint * out_to_id,unsigned int * out_read_lod) const8656 void TextureViewTestCoherency::getReadPropertiesForTextureType(_texture_type texture_type, glw::GLuint *out_to_id,
8657 unsigned int *out_read_lod) const
8658 {
8659 switch (texture_type)
8660 {
8661 case TEXTURE_TYPE_PARENT_TEXTURE:
8662 {
8663 *out_to_id = m_view_to_id;
8664
8665 /* We've modified LOD1 of parent texture which corresponds
8666 * to LOD 0 from the view's PoV
8667 */
8668 *out_read_lod = 0;
8669
8670 break;
8671 }
8672
8673 case TEXTURE_TYPE_TEXTURE_VIEW:
8674 {
8675 *out_to_id = m_to_id;
8676
8677 /* We've modified LOD1 of the view texture which corresponds
8678 * to LOD2 from parent texture's PoV.
8679 */
8680 *out_read_lod = 2;
8681
8682 break;
8683 }
8684
8685 default:
8686 {
8687 TCU_FAIL("Unrecognized read source");
8688 }
8689 } /* switch (texture_type) */
8690 }
8691
8692 /** Allocates a sufficiently large buffer to hold RGBA8 data of user-specified resolution
8693 * and fills it with a static color (as described in the test specification)
8694 *
8695 * It is caller's responsibility to release the returned buffer when it's no longer
8696 * needed.
8697 *
8698 * @param width Width of the mip-map the buffer will be used as a data source for;
8699 * @param height Height of the mip-map the buffer will be used as a data source for;
8700 *
8701 * @return Pointer to the buffer.
8702 **/
getStaticColorTextureData(unsigned int width,unsigned int height) const8703 unsigned char *TextureViewTestCoherency::getStaticColorTextureData(unsigned int width, unsigned int height) const
8704 {
8705 /* Prepare the data buffer storing the data we want to replace the region of the
8706 * data source with.
8707 */
8708 unsigned char *result_ptr = new unsigned char[width * height * m_texture_n_components];
8709
8710 for (unsigned int y = 0; y < height; ++y)
8711 {
8712 unsigned char *row_data_ptr = result_ptr + y * width * m_texture_n_components;
8713
8714 for (unsigned int x = 0; x < width; ++x)
8715 {
8716 unsigned char *pixel_data_ptr = row_data_ptr + x * m_texture_n_components;
8717
8718 memcpy(pixel_data_ptr, m_static_color_byte, sizeof(m_static_color_byte));
8719 } /* for (all columns) */
8720 } /* for (all rows) */
8721
8722 return result_ptr;
8723 }
8724
8725 /** Retrieves properties of a parent texture object that should be written to during
8726 * some of the checks.
8727 *
8728 * @param texture_type Type of the texture object that should be used for writing.
8729 * @param out_to_id Deref will be used to store texture object ID of the object. Must not be NULL.
8730 * @param out_width Deref will be used to store width of the mip-map the test will
8731 * be writing to; Must not be NULL.
8732 * @param out_height Deref will be used to store height of the mip-map the test will
8733 * be writing to. Must not be NULL.
8734 *
8735 **/
getWritePropertiesForTextureType(_texture_type texture_type,glw::GLuint * out_to_id,unsigned int * out_width,unsigned int * out_height) const8736 void TextureViewTestCoherency::getWritePropertiesForTextureType(_texture_type texture_type, glw::GLuint *out_to_id,
8737 unsigned int *out_width, unsigned int *out_height) const
8738 {
8739 DE_ASSERT(out_to_id != DE_NULL);
8740 DE_ASSERT(out_width != DE_NULL);
8741 DE_ASSERT(out_height != DE_NULL);
8742
8743 /* All tests will be attempting to modify layer 1 of either the texture
8744 * or its sibling view. For views, the resolution is therefore going to
8745 * be 16x16 (because the base resolution is 32x32, as the view uses a mipmap
8746 * range of 1 to 2 inclusive); for parent texture, this will be 32x32 (as the base
8747 * mip-map is 64x64)
8748 */
8749 switch (texture_type)
8750 {
8751 case TEXTURE_TYPE_PARENT_TEXTURE:
8752 {
8753 *out_to_id = m_to_id;
8754 *out_width = m_texture_width >> 1;
8755 *out_height = m_texture_height >> 1;
8756
8757 break;
8758 }
8759
8760 case TEXTURE_TYPE_TEXTURE_VIEW:
8761 {
8762 *out_to_id = m_view_to_id;
8763 *out_width = m_texture_width >> 2;
8764 *out_height = m_texture_height >> 2;
8765
8766 break;
8767 }
8768
8769 default:
8770 {
8771 TCU_FAIL("Unrecognized texture type");
8772 }
8773 } /* switch (texture_type) */
8774 }
8775
8776 /** Initializes buffer objects that will be used during the test.
8777 *
8778 * Throws exceptions if the initialization fails at any point.
8779 **/
initBufferObjects()8780 void TextureViewTestCoherency::initBufferObjects()
8781 {
8782 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
8783
8784 /* Generate and configure buffer object storage */
8785 gl.genBuffers(1, &m_bo_id);
8786 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
8787
8788 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id);
8789 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
8790
8791 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_bo_id);
8792 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
8793
8794 /* Case 1) needs the BO to hold just a single int.
8795 * Case 3) needs one int per result texel.
8796 *
8797 * Allocate enough space to handle all the cases.
8798 **/
8799 glw::GLint bo_size = static_cast<glw::GLint>((m_texture_height >> 1) * (m_texture_width >> 1) * sizeof(int));
8800
8801 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bo_size, DE_NULL, /* data */
8802 GL_STATIC_DRAW);
8803 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferdata() call failed.");
8804 }
8805
8806 /** Initializes framebuffer objects that will be used during the test.
8807 *
8808 * Throws exceptions if the initialization fails at any point.
8809 **/
initFBO()8810 void TextureViewTestCoherency::initFBO()
8811 {
8812 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
8813
8814 /* Generate framebuffer object(s) */
8815 gl.genFramebuffers(1, &m_draw_fbo_id);
8816 gl.genFramebuffers(1, &m_read_fbo_id);
8817 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
8818 }
8819
8820 /** Initializes program objects that will be used during the test.
8821 *
8822 * This method will throw exceptions if either compilation or linking of
8823 * any of the processed shaders/programs fails.
8824 *
8825 **/
initPrograms()8826 void TextureViewTestCoherency::initPrograms()
8827 {
8828 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
8829
8830 /* The test uses images in vertex shader stage. Make sure this is actually supported by
8831 * the implementation */
8832 m_are_images_supported = m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_image_load_store");
8833
8834 if (m_are_images_supported)
8835 {
8836 glw::GLint gl_max_vertex_image_uniforms_value = 0;
8837
8838 gl.getIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &gl_max_vertex_image_uniforms_value);
8839 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed for GL_MAX_VERTEX_IMAGE_UNIFORM pname");
8840
8841 if (gl_max_vertex_image_uniforms_value < 1)
8842 {
8843 m_testCtx.getLog() << tcu::TestLog::Message
8844 << "Image support will not be tested by view_parent_texture_coherency, as"
8845 "the implementation does not support image uniforms in vertex shader stage."
8846 << tcu::TestLog::EndMessage;
8847
8848 /* We cannot execute the test on this platform */
8849 m_are_images_supported = false;
8850 }
8851 } /* if (m_are_images_supported) */
8852
8853 /* Create program objects */
8854 if (m_are_images_supported)
8855 {
8856 m_gradient_image_write_po_id = gl.createProgram();
8857 }
8858
8859 m_gradient_verification_po_id = gl.createProgram();
8860 m_gradient_write_po_id = gl.createProgram();
8861 m_verification_po_id = gl.createProgram();
8862 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call(s) failed.");
8863
8864 /* Create fragment shader objects */
8865 m_gradient_write_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
8866 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed for GL_FRAGMENT_SHADER type");
8867
8868 /* Create vertex shader objects */
8869 if (m_are_images_supported)
8870 {
8871 m_gradient_image_write_vs_id = gl.createShader(GL_VERTEX_SHADER);
8872 }
8873
8874 m_gradient_verification_vs_id = gl.createShader(GL_VERTEX_SHADER);
8875 m_gradient_write_vs_id = gl.createShader(GL_VERTEX_SHADER);
8876 m_verification_vs_id = gl.createShader(GL_VERTEX_SHADER);
8877 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed for GL_VERTEX_SHADER type.");
8878
8879 /* Set gradient verification program's fragment shader body */
8880 const char *gradient_verification_vs_body =
8881 "#version 400\n"
8882 "\n"
8883 "out int result;\n"
8884 "\n"
8885 "uniform float lod;\n"
8886 "uniform bool sample_exact_uv;\n"
8887 "uniform sampler2D texture;\n"
8888 "\n"
8889 "void main()\n"
8890 "{\n"
8891 " const float epsilon = 1.0 / 255.0;\n"
8892 " const vec4 end_rgba = vec4(0.0, 0.1, 1.0, 1.0);\n"
8893 " const vec4 start_rgba = vec4(1.0, 0.9, 0.0, 0.0);\n"
8894 "\n"
8895 " ivec2 texture_size = textureSize(texture, int(lod) );\n"
8896 " vec2 uv = vec2( float(gl_VertexID % texture_size.x) / float(texture_size.x),\n"
8897 " 1.0 - float(gl_VertexID / texture_size.x) / float(texture_size.y) );\n"
8898 " vec4 expected_color;\n"
8899 " vec4 texture_color = textureLod(texture, uv, lod);\n"
8900 "\n"
8901 " if (sample_exact_uv)\n"
8902 " {\n"
8903 " expected_color = mix(start_rgba, end_rgba, uv.x);\n"
8904 " }\n"
8905 " else\n"
8906 " {\n"
8907 " expected_color = mix(start_rgba, end_rgba, uv.x + 0.5/float(texture_size.x) );\n"
8908 " }\n"
8909 "\n"
8910 "\n"
8911 " if (abs(texture_color.x - expected_color.x) > epsilon ||\n"
8912 " abs(texture_color.y - expected_color.y) > epsilon ||\n"
8913 " abs(texture_color.z - expected_color.z) > epsilon ||\n"
8914 " abs(texture_color.w - expected_color.w) > epsilon)\n"
8915 " {\n"
8916 " result = int( texture_color.y * 255.0);\n"
8917 " }\n"
8918 " else\n"
8919 " {\n"
8920 " result = 1;\n"
8921 " }\n"
8922 "}\n";
8923
8924 gl.shaderSource(m_gradient_verification_vs_id, 1 /* count */, &gradient_verification_vs_body, NULL /* length */);
8925 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
8926
8927 /* Set gradient write (for images) program's vertex shader body */
8928 if (m_are_images_supported)
8929 {
8930 const char *gradient_write_image_vs_body =
8931 "#version 400\n"
8932 "\n"
8933 "#extension GL_ARB_shader_image_load_store : require\n"
8934 "\n"
8935 "layout(rgba8) uniform image2D image;\n"
8936 " uniform ivec2 image_size;\n"
8937 "\n"
8938 "void main()\n"
8939 "{\n"
8940 " const vec4 end_rgba = vec4(0.0, 0.1, 1.0, 1.0);\n"
8941 " const vec4 start_rgba = vec4(1.0, 0.9, 0.0, 0.0);\n"
8942 " ivec2 xy = ivec2(gl_VertexID % image_size.x, gl_VertexID / image_size.x);\n"
8943 " vec2 uv = vec2(float(xy.x) / float(image_size.x), 1.0 - float(xy.y) / "
8944 "float(image_size.y) );\n"
8945 " vec4 result = mix (start_rgba, end_rgba, uv.x);\n"
8946 "\n"
8947 " imageStore(image, xy, result);\n"
8948 "}\n";
8949
8950 gl.shaderSource(m_gradient_image_write_vs_id, 1 /* count */, &gradient_write_image_vs_body, NULL /* length */);
8951 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
8952 }
8953
8954 /* Set gradient write program's fragment shader body */
8955 const char *gradient_write_fs_body = "#version 400\n"
8956 "\n"
8957 "in vec2 uv;\n"
8958 "\n"
8959 "layout(location = 0) out vec4 result;\n"
8960 "\n"
8961 "void main()\n"
8962 "{\n"
8963 " const vec4 end_rgba = vec4(0.0, 0.1, 1.0, 1.0);\n"
8964 " const vec4 start_rgba = vec4(1.0, 0.9, 0.0, 0.0);\n"
8965 "\n"
8966 " result = mix(start_rgba, end_rgba, uv.x);\n"
8967 "}\n";
8968
8969 gl.shaderSource(m_gradient_write_fs_id, 1 /* count */, &gradient_write_fs_body, NULL /* length */);
8970 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
8971
8972 /* Set gradient write program's vertex shader body */
8973 const char *gradient_write_vs_body =
8974 "#version 400\n"
8975 "\n"
8976 "out vec2 uv;\n"
8977 "\n"
8978 "void main()\n"
8979 "{\n"
8980 " switch (gl_VertexID)\n"
8981 " {\n"
8982 " case 0: gl_Position = vec4(-1.0, -1.0, 0.0, 1.0); uv = vec2(0.0, 1.0); break;\n"
8983 " case 1: gl_Position = vec4(-1.0, 1.0, 0.0, 1.0); uv = vec2(0.0, 0.0); break;\n"
8984 " case 2: gl_Position = vec4( 1.0, -1.0, 0.0, 1.0); uv = vec2(1.0, 1.0); break;\n"
8985 " case 3: gl_Position = vec4( 1.0, 1.0, 0.0, 1.0); uv = vec2(1.0, 0.0); break;\n"
8986 " }\n"
8987 "}\n";
8988
8989 gl.shaderSource(m_gradient_write_vs_id, 1 /* count */, &gradient_write_vs_body, NULL /* length */);
8990 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
8991
8992 /* Set verification program's vertex shader body */
8993 const char *verification_vs_body = "#version 400\n"
8994 "\n"
8995 "uniform vec4 expected_color;\n"
8996 "uniform int lod;\n"
8997 "uniform sampler2D sampler;\n"
8998 "\n"
8999 "out int result;\n"
9000 "\n"
9001 "void main()\n"
9002 "{\n"
9003 " const float epsilon = 1.0 / 256.0;\n"
9004 "\n"
9005 " vec4 sampled_data = textureLod(sampler, vec2(0.5, 0.5), lod);\n"
9006 "\n"
9007 " if (abs(sampled_data.x - expected_color.x) > epsilon ||\n"
9008 " abs(sampled_data.y - expected_color.y) > epsilon ||\n"
9009 " abs(sampled_data.z - expected_color.z) > epsilon ||\n"
9010 " abs(sampled_data.w - expected_color.w) > epsilon)\n"
9011 " {\n"
9012 " result = 0;\n"
9013 " }\n"
9014 " else\n"
9015 " {\n"
9016 " result = 1;\n"
9017 " }\n"
9018 "}\n";
9019
9020 gl.shaderSource(m_verification_vs_id, 1 /* count */, &verification_vs_body, NULL /* length */);
9021 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
9022
9023 /* Compile the shaders */
9024 const glw::GLuint so_ids[] = {m_gradient_image_write_vs_id, m_gradient_verification_vs_id, m_gradient_write_fs_id,
9025 m_gradient_write_vs_id, m_verification_vs_id};
9026 const unsigned int n_so_ids = sizeof(so_ids) / sizeof(so_ids[0]);
9027
9028 for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id)
9029 {
9030 glw::GLuint so_id = so_ids[n_so_id];
9031
9032 if (so_id != 0)
9033 {
9034 gl.compileShader(so_id);
9035 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
9036
9037 /* Verify the compilation ended successfully */
9038 glw::GLint compile_status = GL_FALSE;
9039
9040 gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
9041 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
9042
9043 if (compile_status != GL_TRUE)
9044 {
9045 TCU_FAIL("Shader compilation failed.");
9046 }
9047 }
9048 } /* for (all shader objects) */
9049
9050 /* Attach the shaders to relevant programs */
9051 if (m_are_images_supported)
9052 {
9053 gl.attachShader(m_gradient_image_write_po_id, m_gradient_image_write_vs_id);
9054 }
9055
9056 gl.attachShader(m_gradient_verification_po_id, m_gradient_verification_vs_id);
9057 gl.attachShader(m_gradient_write_po_id, m_gradient_write_fs_id);
9058 gl.attachShader(m_gradient_write_po_id, m_gradient_write_vs_id);
9059 gl.attachShader(m_verification_po_id, m_verification_vs_id);
9060 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed.");
9061
9062 /* Set up XFB */
9063 const char *verification_varying_name = "result";
9064 const glw::GLuint xfb_po_ids[] = {
9065 m_gradient_verification_po_id,
9066 m_verification_po_id,
9067 };
9068 const unsigned int n_xfb_po_ids = sizeof(xfb_po_ids) / sizeof(xfb_po_ids[0]);
9069
9070 for (unsigned int n_xfb_po_id = 0; n_xfb_po_id < n_xfb_po_ids; ++n_xfb_po_id)
9071 {
9072 glw::GLint po_id = xfb_po_ids[n_xfb_po_id];
9073
9074 gl.transformFeedbackVaryings(po_id, 1 /* count */, &verification_varying_name, GL_INTERLEAVED_ATTRIBS);
9075 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
9076 }
9077
9078 /* Link the programs */
9079 const glw::GLuint po_ids[] = {m_gradient_image_write_po_id, m_gradient_verification_po_id, m_gradient_write_po_id,
9080 m_verification_po_id};
9081 const unsigned int n_po_ids = sizeof(po_ids) / sizeof(po_ids[0]);
9082
9083 for (unsigned int n_po_id = 0; n_po_id < n_po_ids; ++n_po_id)
9084 {
9085 glw::GLuint po_id = po_ids[n_po_id];
9086
9087 if (po_id != 0)
9088 {
9089 gl.linkProgram(po_id);
9090 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
9091
9092 /* Make sure the linking was successful. */
9093 glw::GLint link_status = GL_FALSE;
9094
9095 gl.getProgramiv(po_id, GL_LINK_STATUS, &link_status);
9096 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
9097
9098 if (link_status != GL_TRUE)
9099 {
9100 TCU_FAIL("Program linking failed.");
9101 }
9102 }
9103 } /* for (all program objects) */
9104
9105 /* Retrieve uniform locations for gradient write program (image case) */
9106 if (m_are_images_supported)
9107 {
9108 m_gradient_image_write_image_size_location = gl.getUniformLocation(m_gradient_image_write_po_id, "image_size");
9109
9110 if (m_gradient_image_write_image_size_location == -1)
9111 {
9112 TCU_FAIL("image_size is considered an inactive uniform which is invalid.");
9113 }
9114 }
9115
9116 /* Retrieve uniform locations for gradient verification program */
9117 m_gradient_verification_po_sample_exact_uv_location =
9118 gl.getUniformLocation(m_gradient_verification_po_id, "sample_exact_uv");
9119 m_gradient_verification_po_lod_location = gl.getUniformLocation(m_gradient_verification_po_id, "lod");
9120 m_gradient_verification_po_texture_location = gl.getUniformLocation(m_gradient_verification_po_id, "texture");
9121
9122 if (m_gradient_verification_po_sample_exact_uv_location == -1)
9123 {
9124 TCU_FAIL("sample_exact_uv is considered an inactive uniform which is invalid");
9125 }
9126
9127 if (m_gradient_verification_po_lod_location == -1)
9128 {
9129 TCU_FAIL("lod is considered an inactive uniform which is invalid.");
9130 }
9131
9132 if (m_gradient_verification_po_texture_location == -1)
9133 {
9134 TCU_FAIL("texture is considered an inactive uniform which is invalid.");
9135 }
9136
9137 /* Retrieve uniform locations for verification program */
9138 m_verification_po_expected_color_location = gl.getUniformLocation(m_verification_po_id, "expected_color");
9139 m_verification_po_lod_location = gl.getUniformLocation(m_verification_po_id, "lod");
9140
9141 if (m_verification_po_expected_color_location == -1)
9142 {
9143 TCU_FAIL("expected_color is considered an inactive uniform which is invalid.");
9144 }
9145
9146 if (m_verification_po_lod_location == -1)
9147 {
9148 TCU_FAIL("lod is considered an inactive uniform which is invalid.");
9149 }
9150 }
9151
9152 /** Initializes texture objects required to run the test.
9153 *
9154 * Throws exceptions if the initialization fails at any point.
9155 **/
initTextures()9156 void TextureViewTestCoherency::initTextures()
9157 {
9158 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
9159
9160 /* Generate the texture objects */
9161 gl.genTextures(1, &m_static_to_id);
9162 gl.genTextures(1, &m_to_id);
9163 gl.genTextures(1, &m_view_to_id);
9164 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call(s) failed.");
9165
9166 /* Set up parent texture object */
9167 gl.bindTexture(GL_TEXTURE_2D, m_to_id);
9168 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
9169
9170 gl.texStorage2D(GL_TEXTURE_2D, m_texture_n_levels, GL_RGBA8, m_texture_width, m_texture_height);
9171 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
9172
9173 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
9174 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
9175 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9176 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
9177 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() call(s) failed.");
9178
9179 /* Set up the texture views we'll be using for the test */
9180 gl.textureView(m_view_to_id, GL_TEXTURE_2D, m_to_id, GL_RGBA8, 1, /* minlevel */
9181 2, /* numlevels */
9182 0, /* minlayer */
9183 1); /* numlayers */
9184 GLU_EXPECT_NO_ERROR(gl.getError(), "glTextureView() call failed");
9185
9186 gl.bindTexture(GL_TEXTURE_2D, m_view_to_id);
9187 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
9188 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
9189 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9190 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
9191
9192 /* Set up storage for static color texture */
9193 gl.bindTexture(GL_TEXTURE_2D, m_static_to_id);
9194 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
9195
9196 gl.texStorage2D(GL_TEXTURE_2D, 1, /* levels */
9197 GL_RGBA8, m_static_texture_width, m_static_texture_height);
9198 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
9199
9200 /* Fill the texture objects with actual contents */
9201 initTextureContents();
9202 }
9203
9204 /** Fills all relevant mip-maps of all previously initialized texture objects with
9205 * contents.
9206 *
9207 * Throws an exception if any of the issued GL API calls fail.
9208 **/
initTextureContents()9209 void TextureViewTestCoherency::initTextureContents()
9210 {
9211 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
9212
9213 /* Make sure parent texture object is bound before we start modifying
9214 * the mip-maps */
9215 gl.bindTexture(GL_TEXTURE_2D, m_to_id);
9216 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
9217
9218 /* Set up parent texture mip-maps */
9219 unsigned char *base_mipmap_data_ptr = getHorizontalGradientData();
9220
9221 gl.texSubImage2D(GL_TEXTURE_2D, 0, /* level */
9222 0, /* xoffset */
9223 0, /* yoffset */
9224 m_texture_width, m_texture_height, GL_RGBA, GL_UNSIGNED_BYTE, base_mipmap_data_ptr);
9225
9226 delete[] base_mipmap_data_ptr;
9227 base_mipmap_data_ptr = NULL;
9228
9229 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexSubImage2D() call failed.");
9230
9231 /* Generate all mip-maps */
9232 gl.generateMipmap(GL_TEXTURE_2D);
9233 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenerateMipmap() call failed.");
9234
9235 /* Set up static color texture contents. We only need to fill the base mip-map
9236 * since the texture's resolution is 1x1.
9237 */
9238 DE_ASSERT(m_static_texture_height == 1 && m_static_texture_width == 1);
9239
9240 unsigned char *static_texture_data_ptr = getStaticColorTextureData(m_static_texture_width, m_static_texture_height);
9241
9242 gl.bindTexture(GL_TEXTURE_2D, m_static_to_id);
9243 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
9244
9245 gl.texSubImage2D(GL_TEXTURE_2D, 0, /* level */
9246 0, /* xoffset */
9247 0, /* yoffset */
9248 m_static_texture_width, m_static_texture_height, GL_RGBA, GL_UNSIGNED_BYTE,
9249 static_texture_data_ptr);
9250
9251 /* Good to release the buffer at this point */
9252 delete[] static_texture_data_ptr;
9253
9254 static_texture_data_ptr = DE_NULL;
9255
9256 /* Was the API call successful? */
9257 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexSubImage2D() call failed.");
9258 }
9259
9260 /** Initializes a vertex array object used for the draw calls issued during the test. */
initVAO()9261 void TextureViewTestCoherency::initVAO()
9262 {
9263 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
9264
9265 /* Generate and bind a vertex array object */
9266 gl.genVertexArrays(1, &m_vao_id);
9267 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
9268
9269 gl.bindVertexArray(m_vao_id);
9270 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
9271 }
9272
9273 /** Executes test iteration.
9274 *
9275 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
9276 */
iterate()9277 tcu::TestNode::IterateResult TextureViewTestCoherency::iterate()
9278 {
9279 /* Do not execute the test if GL_ARB_texture_view is not supported */
9280 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_texture_view"))
9281 {
9282 throw tcu::NotSupportedError("GL_ARB_texture_view is not supported.");
9283 }
9284
9285 /* Initialize all GL objects required to run the test */
9286 initBufferObjects();
9287 initPrograms();
9288 initTextures();
9289 initFBO();
9290 initVAO();
9291
9292 /* Iterate over the set of texture types we are to test */
9293 const _texture_type texture_types[] = {TEXTURE_TYPE_PARENT_TEXTURE, TEXTURE_TYPE_TEXTURE_VIEW};
9294 const unsigned int n_texture_types = sizeof(texture_types) / sizeof(texture_types[0]);
9295
9296 for (unsigned int n_texture_type = 0; n_texture_type < n_texture_types; ++n_texture_type)
9297 {
9298 _texture_type texture_type = texture_types[n_texture_type];
9299
9300 /* Verify parent texture/view coherency when using glTexSubImage2D() */
9301 checkAPICallCoherency(texture_type, true);
9302
9303 /* Verify parent texture/view coherency when using glBlitFramebuffer() */
9304 checkAPICallCoherency(texture_type, false);
9305
9306 /* Verify parent texture/view coherency when modifying contents of one
9307 * of the objects in a program, and then reading the sibling from another
9308 * program.
9309 */
9310 checkProgramWriteCoherency(texture_type, false, /* should_use_images */
9311 BARRIER_TYPE_NONE, VERIFICATION_MEAN_PROGRAM);
9312
9313 if (m_are_images_supported)
9314 {
9315 /* Verify a view bound to an image unit and written to using image uniforms
9316 * in vertex shader stage can later be sampled correctly, assuming
9317 * a GL_TEXTURE_FETCH_BARRIER_BIT barrier is inserted between the write
9318 * operations and sampling from another program object.
9319 */
9320 checkProgramWriteCoherency(texture_type, true, /* should_use_images */
9321 BARRIER_TYPE_TEXTURE_FETCH_BARRIER_BIT, VERIFICATION_MEAN_PROGRAM);
9322
9323 /* Verify a view bound to an image unit and written to using image uniforms
9324 * in vertex shader stage can later be correctly retrieved using a glGetTexImage()
9325 * call, assuming a GL_TEXTURE_UPDATE_BARRIER_BIT barrier is inserted between the
9326 * two operations.
9327 **/
9328 checkProgramWriteCoherency(texture_type, true, /* should_use_images */
9329 BARRIER_TYPE_TEXTURE_UPDATE_BUFFER_BIT, VERIFICATION_MEAN_GLGETTEXIMAGE);
9330 }
9331
9332 /* Reinitialize all texture contents */
9333 initTextureContents();
9334 } /* for (all read sources) */
9335
9336 /* Test case passed */
9337 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
9338
9339 return STOP;
9340 }
9341
9342 /** Constructor.
9343 *
9344 * @param context Rendering context.
9345 *
9346 **/
TextureViewTestBaseAndMaxLevels(deqp::Context & context)9347 TextureViewTestBaseAndMaxLevels::TextureViewTestBaseAndMaxLevels(deqp::Context &context)
9348 : TestCase(context, "base_and_max_levels", "test_description")
9349 , m_texture_height(256)
9350 , m_texture_n_components(4)
9351 , m_texture_n_levels(6)
9352 , m_texture_width(256)
9353 , m_view_height(128)
9354 , m_view_width(128)
9355 , m_layer_data_lod0(DE_NULL)
9356 , m_layer_data_lod1(DE_NULL)
9357 , m_fbo_id(0)
9358 , m_fs_id(0)
9359 , m_po_id(0)
9360 , m_po_lod_index_uniform_location(-1)
9361 , m_po_to_sampler_uniform_location(-1)
9362 , m_result_to_id(0)
9363 , m_to_id(0)
9364 , m_vao_id(0)
9365 , m_view_to_id(0)
9366 , m_vs_id(0)
9367 {
9368 /* Left blank on purpose */
9369 }
9370
9371 /* Deinitializes all GL objects that may have been created during test execution. */
deinit()9372 void TextureViewTestBaseAndMaxLevels::deinit()
9373 {
9374 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
9375
9376 if (m_fbo_id != 0)
9377 {
9378 gl.deleteFramebuffers(1, &m_fbo_id);
9379
9380 m_fbo_id = 0;
9381 }
9382
9383 if (m_fs_id != 0)
9384 {
9385 gl.deleteShader(m_fs_id);
9386
9387 m_fs_id = 0;
9388 }
9389
9390 if (m_layer_data_lod0 != DE_NULL)
9391 {
9392 delete[] m_layer_data_lod0;
9393
9394 m_layer_data_lod0 = DE_NULL;
9395 }
9396
9397 if (m_layer_data_lod1 != DE_NULL)
9398 {
9399 delete[] m_layer_data_lod1;
9400
9401 m_layer_data_lod1 = DE_NULL;
9402 }
9403
9404 if (m_po_id != 0)
9405 {
9406 gl.deleteProgram(m_po_id);
9407
9408 m_po_id = 0;
9409 }
9410
9411 if (m_result_to_id != 0)
9412 {
9413 gl.deleteTextures(1, &m_result_to_id);
9414
9415 m_result_to_id = 0;
9416 }
9417
9418 if (m_to_id != 0)
9419 {
9420 gl.deleteTextures(1, &m_to_id);
9421
9422 m_to_id = 0;
9423 }
9424
9425 if (m_vao_id != 0)
9426 {
9427 gl.deleteVertexArrays(1, &m_vao_id);
9428
9429 m_vao_id = 0;
9430 }
9431
9432 if (m_view_to_id != 0)
9433 {
9434 gl.deleteTextures(1, &m_view_to_id);
9435
9436 m_view_to_id = 0;
9437 }
9438
9439 if (m_vs_id != 0)
9440 {
9441 gl.deleteShader(m_vs_id);
9442
9443 m_vs_id = 0;
9444 }
9445 }
9446
9447 /* Initializes and configures a program object used later by the test. */
initProgram()9448 void TextureViewTestBaseAndMaxLevels::initProgram()
9449 {
9450 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
9451
9452 /* Generate shader object IDs */
9453 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
9454 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
9455
9456 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed");
9457
9458 /* Generate program object ID */
9459 m_po_id = gl.createProgram();
9460
9461 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed");
9462
9463 /* Set up vertex shader body */
9464 static const char *vs_body =
9465 "#version 400\n"
9466 "\n"
9467 "out vec2 uv;\n"
9468 "\n"
9469 "void main()\n"
9470 "{\n"
9471 " switch (gl_VertexID)\n"
9472 " {\n"
9473 " case 0: gl_Position = vec4(-1.0, 1.0, 0.0, 1.0); uv = vec2(0.0, 1.0); break;\n"
9474 " case 1: gl_Position = vec4(-1.0, -1.0, 0.0, 1.0); uv = vec2(0.0, 0.0); break;\n"
9475 " case 2: gl_Position = vec4( 1.0, 1.0, 0.0, 1.0); uv = vec2(1.0, 1.0); break;\n"
9476 " case 3: gl_Position = vec4( 1.0, -1.0, 0.0, 1.0); uv = vec2(1.0, 0.0); break;\n"
9477 " };\n"
9478 "}\n";
9479
9480 gl.shaderSource(m_vs_id, 1 /* count */, &vs_body, DE_NULL /* length */);
9481 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed for vertex shader case");
9482
9483 /* Set up fragment shader body */
9484 static const char *fs_body = "#version 400\n"
9485 "\n"
9486 "in vec2 uv;\n"
9487 "\n"
9488 "uniform int lod_index;\n"
9489 "uniform sampler2D to_sampler;\n"
9490 "\n"
9491 "out vec4 result;\n"
9492 "\n"
9493 "void main()\n"
9494 "{\n"
9495 " result = textureLod(to_sampler, uv, float(lod_index) );\n"
9496 "}\n";
9497
9498 gl.shaderSource(m_fs_id, 1 /* count */, &fs_body, DE_NULL /* length */);
9499 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed for fragment shader case");
9500
9501 /* Compile both shaders */
9502 const glw::GLuint so_ids[] = {m_fs_id, m_vs_id};
9503 const unsigned int n_so_ids = sizeof(so_ids) / sizeof(so_ids[0]);
9504
9505 for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id)
9506 {
9507 glw::GLint so_id = so_ids[n_so_id];
9508
9509 gl.compileShader(so_id);
9510 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
9511
9512 /* Make sure the compilation has succeeded */
9513 glw::GLint compile_status = GL_FALSE;
9514
9515 gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
9516 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
9517
9518 if (compile_status != GL_TRUE)
9519 {
9520 m_testCtx.getLog() << tcu::TestLog::Message << "Shader compilation failed" << tcu::TestLog::EndMessage;
9521 }
9522 } /* for (all shader objects) */
9523
9524 /* Attach the shaders to the program object */
9525 gl.attachShader(m_po_id, m_fs_id);
9526 gl.attachShader(m_po_id, m_vs_id);
9527 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed");
9528
9529 /* Link the program object */
9530 gl.linkProgram(m_po_id);
9531 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call faikled");
9532
9533 /* Verify the linking has succeeded */
9534 glw::GLint link_status = GL_FALSE;
9535
9536 gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
9537 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed for GL_LINK_STATUS pname");
9538
9539 if (link_status != GL_TRUE)
9540 {
9541 TCU_FAIL("Program linking failed");
9542 }
9543
9544 /* Retrieve uniform locations */
9545 m_po_lod_index_uniform_location = gl.getUniformLocation(m_po_id, "lod_index");
9546 m_po_to_sampler_uniform_location = gl.getUniformLocation(m_po_id, "to_sampler");
9547
9548 if (m_po_lod_index_uniform_location == -1)
9549 {
9550 TCU_FAIL("lod_index is considered an inactive uniform");
9551 }
9552
9553 if (m_po_to_sampler_uniform_location == -1)
9554 {
9555 TCU_FAIL("to_sampler is considered an inactive uniform");
9556 }
9557 }
9558
9559 /* Initializes all GL objects used by the test. */
initTest()9560 void TextureViewTestBaseAndMaxLevels::initTest()
9561 {
9562 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
9563
9564 /* Initialize textures */
9565 initTextures();
9566
9567 /* Initialize framebuffer and configure its attachments */
9568 gl.genFramebuffers(1, &m_fbo_id);
9569 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed");
9570
9571 /* Build the program we'll need for the test */
9572 initProgram();
9573
9574 /* Generate a vertex array object to execute the draw calls */
9575 gl.genVertexArrays(1, &m_vao_id);
9576 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
9577
9578 gl.bindVertexArray(m_vao_id);
9579 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
9580
9581 /* Finally, allocate space for buffers that will be filled with rendered data */
9582 m_layer_data_lod0 = new unsigned char[m_texture_width * m_texture_height * m_texture_n_components];
9583 m_layer_data_lod1 = new unsigned char[(m_texture_width >> 1) * (m_texture_height >> 1) * m_texture_n_components];
9584
9585 if (m_layer_data_lod0 == DE_NULL || m_layer_data_lod1 == DE_NULL)
9586 {
9587 TCU_FAIL("Out of memory");
9588 }
9589 }
9590
9591 /** Initializes texture objects used by the test. */
initTextures()9592 void TextureViewTestBaseAndMaxLevels::initTextures()
9593 {
9594 /* Generate IDs first */
9595 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
9596
9597 gl.genTextures(1, &m_result_to_id);
9598 gl.genTextures(1, &m_to_id);
9599 gl.genTextures(1, &m_view_to_id);
9600 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call(s) failed");
9601
9602 /* Set up parent texture object's storage */
9603 gl.bindTexture(GL_TEXTURE_2D, m_to_id);
9604 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
9605
9606 gl.texStorage2D(GL_TEXTURE_2D, m_texture_n_levels, GL_RGBA8, m_texture_width, m_texture_height);
9607 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed");
9608
9609 /* Configure GL_TEXTURE_BASE_LEVEL parameter of the texture object as per test spec */
9610 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 2);
9611 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() call failed for GL_TEXTURE_BASE_LEVEL pname");
9612
9613 /* Configure GL_TEXTURE_MAX_LEVEL parameter of the texture object as per test spec */
9614 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 4);
9615 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() call failed for GL_TEXTURE_MAX_LEVEL pname");
9616
9617 /* Set up mip-maps */
9618 for (unsigned int n_mipmap = 0; n_mipmap < m_texture_n_levels; ++n_mipmap)
9619 {
9620 const float start_rgba[] = {/* As per test specification */
9621 float(n_mipmap + 0) / 10.0f, float(n_mipmap + 1) / 10.0f,
9622 float(n_mipmap + 2) / 10.0f, float(n_mipmap + 3) / 10.0f};
9623 const float end_rgba[] = {float(10 - (n_mipmap + 0)) / 10.0f, float(10 - (n_mipmap + 1)) / 10.0f,
9624 float(10 - (n_mipmap + 2)) / 10.0f, float(10 - (n_mipmap + 3)) / 10.0f};
9625
9626 /* Allocate space for the layer data */
9627 const unsigned int mipmap_height = m_texture_height >> n_mipmap;
9628 const unsigned int mipmap_width = m_texture_width >> n_mipmap;
9629 unsigned char *data = new unsigned char[mipmap_width * mipmap_height * m_texture_n_components];
9630
9631 if (data == NULL)
9632 {
9633 TCU_FAIL("Out of memory");
9634 }
9635
9636 /* Fill the buffer with layer data */
9637 const unsigned int pixel_size = 4 /* components */;
9638
9639 for (unsigned int y = 0; y < mipmap_height; ++y)
9640 {
9641 unsigned char *row_data_ptr = data + mipmap_width * y * pixel_size;
9642
9643 for (unsigned int x = 0; x < mipmap_width; ++x)
9644 {
9645 const float lerp_factor = float(x) / float(mipmap_width);
9646 unsigned char *pixel_data_ptr = row_data_ptr + x * pixel_size;
9647
9648 for (unsigned int n_component = 0; n_component < m_texture_n_components; n_component++)
9649 {
9650 pixel_data_ptr[n_component] = (unsigned char)((start_rgba[n_component] * lerp_factor +
9651 end_rgba[n_component] * (1.0f - lerp_factor)) *
9652 255.0f);
9653 }
9654 } /* for (all columns) */
9655 } /* for (all rows) */
9656
9657 /* Upload the layer data */
9658 gl.texSubImage2D(GL_TEXTURE_2D, n_mipmap, 0, /* xoffset */
9659 0, /* yoffset */
9660 mipmap_width, mipmap_height, GL_RGBA, GL_UNSIGNED_BYTE, data);
9661
9662 /* Release the data buffer */
9663 delete[] data;
9664
9665 data = DE_NULL;
9666
9667 /* Make sure the API call finished successfully */
9668 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexSubImage2D() call failed");
9669 } /* for (all mip-maps) */
9670
9671 /* Configure the texture view storage as per spec. */
9672 gl.textureView(m_view_to_id, GL_TEXTURE_2D, m_to_id, GL_RGBA8, 0, /* minlevel */
9673 5, /* numlevels */
9674 0, /* minlayer */
9675 1); /* numlayers */
9676 GLU_EXPECT_NO_ERROR(gl.getError(), "glTextureView() call failed");
9677
9678 /* Configure the texture view's GL_TEXTURE_BASE_LEVEL parameter */
9679 gl.bindTexture(GL_TEXTURE_2D, m_view_to_id);
9680 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
9681
9682 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
9683 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() call failed for GL_TEXTURE_BASE_LEVEL pname");
9684
9685 /* Configure the texture view's GL_TEXTURE_MAX_LEVEL parameter */
9686 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
9687 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() call failed for GL_TEXTURE_MAX_LEVEL pname");
9688
9689 /* Set up result texture storage */
9690 gl.bindTexture(GL_TEXTURE_2D, m_result_to_id);
9691 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
9692
9693 gl.texStorage2D(GL_TEXTURE_2D, 1, /* We will only attach the first level of the result texture to the FBO */
9694 GL_RGBA8, m_view_width, m_view_height);
9695 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed");
9696 }
9697
9698 /** Executes test iteration.
9699 *
9700 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
9701 */
iterate()9702 tcu::TestNode::IterateResult TextureViewTestBaseAndMaxLevels::iterate()
9703 {
9704 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
9705
9706 /* Only execute if GL_ARB_texture_view extension is supported */
9707 const std::vector<std::string> &extensions = m_context.getContextInfo().getExtensions();
9708
9709 if (std::find(extensions.begin(), extensions.end(), "GL_ARB_texture_view") == extensions.end())
9710 {
9711 throw tcu::NotSupportedError("GL_ARB_texture_view is not supported");
9712 }
9713
9714 /* Initialize all GL objects necessary to run the test */
9715 initTest();
9716
9717 /* Activate test-wide program object */
9718 gl.useProgram(m_po_id);
9719 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
9720
9721 /* Bind the data texture */
9722 gl.activeTexture(GL_TEXTURE0);
9723 GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture() call failed");
9724
9725 gl.bindTexture(GL_TEXTURE_2D, m_view_to_id);
9726 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
9727
9728 /* We will now use the program to sample the view's LOD 0 and LOD 1 and store
9729 * it in two separate textures.
9730 **/
9731 for (unsigned int lod_level = 0; lod_level < 2; /* as per test spec */
9732 ++lod_level)
9733 {
9734 /* Set up FBO attachments */
9735 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
9736 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed");
9737
9738 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_result_to_id,
9739 0); /* level */
9740 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed");
9741
9742 /* Update viewport configuration */
9743 gl.viewport(0, /* x */
9744 0, /* y */
9745 m_view_width >> lod_level, m_view_height >> lod_level);
9746
9747 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed");
9748
9749 /* Configure program object uniforms before we continue */
9750 gl.uniform1i(m_po_lod_index_uniform_location, lod_level);
9751 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i() call failed.");
9752
9753 /* Render a triangle strip. The program we're using will output a full-screen
9754 * quad with the sampled data */
9755 gl.drawArrays(GL_TRIANGLE_STRIP, 0 /* first */, 4 /* count */);
9756 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
9757
9758 /* At the time of the draw call, we've modified the draw/read framebuffer binding
9759 * so that everything we render ends up in result texture. It's time to read it */
9760 glw::GLvoid *result_data_ptr = (lod_level == 0) ? m_layer_data_lod0 : m_layer_data_lod1;
9761
9762 gl.readPixels(0, /* x */
9763 0, /* y */
9764 m_view_width >> lod_level, m_view_height >> lod_level, GL_RGBA, GL_UNSIGNED_BYTE,
9765 result_data_ptr);
9766
9767 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed");
9768 } /* for (both LODs) */
9769
9770 /* Now that we have both pieces of data, we can proceed with actual verification */
9771 for (unsigned int lod_level = 0; lod_level < 2; ++lod_level)
9772 {
9773 /* NOTE: This code is a modification of initialization routine
9774 * found in initTextures()
9775 */
9776 const unsigned char epsilon = 1;
9777 const glw::GLvoid *layer_data_ptr = (lod_level == 0) ? m_layer_data_lod0 : m_layer_data_lod1;
9778 const unsigned int layer_height = m_view_height >> lod_level;
9779 const unsigned int layer_width = m_view_width >> lod_level;
9780 const unsigned int pixel_size = 4 /* components */;
9781 const unsigned int view_minimum_level = 1; /* THS SHOULD BE 1 */
9782 const float start_rgba[] = {
9783 /* As per test specification */
9784 float(lod_level + view_minimum_level + 0) / 10.0f, float(lod_level + view_minimum_level + 1) / 10.0f,
9785 float(lod_level + view_minimum_level + 2) / 10.0f, float(lod_level + view_minimum_level + 3) / 10.0f};
9786 const float end_rgba[] = {float(10 - (lod_level + view_minimum_level + 0)) / 10.0f,
9787 float(10 - (lod_level + view_minimum_level + 1)) / 10.0f,
9788 float(10 - (lod_level + view_minimum_level + 2)) / 10.0f,
9789 float(10 - (lod_level + view_minimum_level + 3)) / 10.0f};
9790
9791 for (unsigned int y = 0; y < layer_height; ++y)
9792 {
9793 const unsigned char *row_data_ptr = (const unsigned char *)layer_data_ptr + layer_width * y * pixel_size;
9794
9795 for (unsigned int x = 0; x < layer_width; ++x)
9796 {
9797 const float lerp_factor = float(x) / float(layer_width);
9798 const unsigned char *pixel_data_ptr = row_data_ptr + x * pixel_size;
9799
9800 const unsigned char expected_data[] = {
9801 (unsigned char)((start_rgba[0] * lerp_factor + end_rgba[0] * (1.0f - lerp_factor)) * 255.0f),
9802 (unsigned char)((start_rgba[1] * lerp_factor + end_rgba[1] * (1.0f - lerp_factor)) * 255.0f),
9803 (unsigned char)((start_rgba[2] * lerp_factor + end_rgba[2] * (1.0f - lerp_factor)) * 255.0f),
9804 (unsigned char)((start_rgba[3] * lerp_factor + end_rgba[3] * (1.0f - lerp_factor)) * 255.0f)};
9805
9806 if (de::abs(expected_data[0] - pixel_data_ptr[0]) > epsilon ||
9807 de::abs(expected_data[1] - pixel_data_ptr[1]) > epsilon ||
9808 de::abs(expected_data[2] - pixel_data_ptr[2]) > epsilon ||
9809 de::abs(expected_data[3] - pixel_data_ptr[3]) > epsilon)
9810 {
9811 m_testCtx.getLog() << tcu::TestLog::Message << "Found an invalid texel at (" << x << ", " << y
9812 << ");"
9813 " expected value:"
9814 "("
9815 << expected_data[0] << ", " << expected_data[1] << ", " << expected_data[2]
9816 << ", " << expected_data[3]
9817 << ")"
9818 ", found:"
9819 "("
9820 << pixel_data_ptr[0] << ", " << pixel_data_ptr[1] << ", " << pixel_data_ptr[2]
9821 << ", " << pixel_data_ptr[3] << ")" << tcu::TestLog::EndMessage;
9822
9823 TCU_FAIL("Rendered data does not match expected pixel data");
9824 } /* if (pixel mismatch found) */
9825 } /* for (all columns) */
9826 } /* for (all rows) */
9827 } /* for (both LODs) */
9828
9829 /* Test case passed */
9830 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
9831
9832 return STOP;
9833 }
9834
9835 /** Constructor.
9836 *
9837 * @param context Rendering context.
9838 **/
TextureViewTestReferenceCounting(deqp::Context & context)9839 TextureViewTestReferenceCounting::TextureViewTestReferenceCounting(deqp::Context &context)
9840 : TestCase(context, "reference_counting",
9841 "Makes sure that sampling from views, for which the parent texture object "
9842 "has already been deleted, works correctly.")
9843 , m_bo_id(0)
9844 , m_parent_to_id(0)
9845 , m_po_id(0)
9846 , m_po_expected_texel_uniform_location(-1)
9847 , m_po_lod_uniform_location(-1)
9848 , m_vao_id(0)
9849 , m_view_to_id(0)
9850 , m_view_view_to_id(0)
9851 , m_vs_id(0)
9852 , m_texture_height(64)
9853 , m_texture_n_levels(7)
9854 , m_texture_width(64)
9855 {
9856 /* Configure a vector storing unique colors that should be used
9857 * for filling subsequent mip-maps of parent texture */
9858 m_mipmap_colors.push_back(_norm_vec4(123, 34, 56, 78));
9859 m_mipmap_colors.push_back(_norm_vec4(234, 45, 67, 89));
9860 m_mipmap_colors.push_back(_norm_vec4(34, 56, 78, 90));
9861 m_mipmap_colors.push_back(_norm_vec4(45, 67, 89, 1));
9862 m_mipmap_colors.push_back(_norm_vec4(56, 78, 90, 123));
9863 m_mipmap_colors.push_back(_norm_vec4(67, 89, 1, 234));
9864 m_mipmap_colors.push_back(_norm_vec4(78, 90, 12, 34));
9865
9866 DE_ASSERT(m_mipmap_colors.size() == m_texture_n_levels);
9867 }
9868
9869 /** Deinitializes all GL objects that may have been created during test
9870 * execution.
9871 **/
deinit()9872 void TextureViewTestReferenceCounting::deinit()
9873 {
9874 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
9875
9876 if (m_bo_id != 0)
9877 {
9878 gl.deleteBuffers(1, &m_bo_id);
9879
9880 m_bo_id = 0;
9881 }
9882
9883 if (m_parent_to_id != 0)
9884 {
9885 gl.deleteTextures(1, &m_parent_to_id);
9886
9887 m_parent_to_id = 0;
9888 }
9889
9890 if (m_po_id != 0)
9891 {
9892 gl.deleteProgram(m_po_id);
9893
9894 m_po_id = 0;
9895 }
9896
9897 if (m_vao_id != 0)
9898 {
9899 gl.deleteVertexArrays(1, &m_vao_id);
9900
9901 m_vao_id = 0;
9902 }
9903
9904 if (m_view_to_id != 0)
9905 {
9906 gl.deleteTextures(1, &m_view_to_id);
9907
9908 m_view_to_id = 0;
9909 }
9910
9911 if (m_view_view_to_id != 0)
9912 {
9913 gl.deleteTextures(1, &m_view_view_to_id);
9914
9915 m_view_view_to_id = 0;
9916 }
9917
9918 if (m_vs_id != 0)
9919 {
9920 gl.deleteShader(m_vs_id);
9921
9922 m_vs_id = 0;
9923 }
9924 }
9925
9926 /* Initializes a program object to be used during the test. */
initProgram()9927 void TextureViewTestReferenceCounting::initProgram()
9928 {
9929 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
9930
9931 /* Create program & shader object IDs */
9932 m_po_id = gl.createProgram();
9933 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed");
9934
9935 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
9936 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed");
9937
9938 /* Set vertex shader body */
9939 const char *vs_body = "#version 400\n"
9940 "\n"
9941 "uniform vec4 expected_texel;\n"
9942 "uniform int lod;\n"
9943 "uniform sampler2D sampler;\n"
9944 "\n"
9945 "out int has_passed;\n"
9946 "\n"
9947 "void main()\n"
9948 "{\n"
9949 " vec4 data = textureLod(sampler, vec2(0.5, 0.5), lod);\n"
9950 " const float epsilon = 1.0 / 256.0;\n"
9951 "\n"
9952 " if (abs(data.r - expected_texel.r) > epsilon ||\n"
9953 " abs(data.g - expected_texel.g) > epsilon ||\n"
9954 " abs(data.b - expected_texel.b) > epsilon ||\n"
9955 " abs(data.a - expected_texel.a) > epsilon)\n"
9956 " {\n"
9957 " has_passed = 0;\n"
9958 " }\n"
9959 " else\n"
9960 " {\n"
9961 " has_passed = 1;\n"
9962 " }\n"
9963 "}\n";
9964
9965 gl.shaderSource(m_vs_id, 1 /* count */, &vs_body, NULL /* length */);
9966 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed");
9967
9968 /* Configure XFB */
9969 const char *varying_name = "has_passed";
9970
9971 gl.transformFeedbackVaryings(m_po_id, 1 /* count */, &varying_name, GL_INTERLEAVED_ATTRIBS);
9972 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed");
9973
9974 /* Attach the shader object to the program */
9975 gl.attachShader(m_po_id, m_vs_id);
9976 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed");
9977
9978 /* Compile the shader */
9979 gl.compileShader(m_vs_id);
9980 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
9981
9982 /* Make sure the compilation has succeeded */
9983 glw::GLint compile_status = GL_FALSE;
9984
9985 gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
9986 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
9987
9988 if (compile_status != GL_TRUE)
9989 {
9990 m_testCtx.getLog() << tcu::TestLog::Message << "Shader compilation failed" << tcu::TestLog::EndMessage;
9991 }
9992
9993 /* Link the program object */
9994 gl.linkProgram(m_po_id);
9995 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed");
9996
9997 /* Make sure the program object has linked successfully */
9998 glw::GLint link_status = GL_FALSE;
9999
10000 gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
10001 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed");
10002
10003 if (link_status != GL_TRUE)
10004 {
10005 TCU_FAIL("Program linking failed");
10006 }
10007
10008 /* Retrieve uniform locations */
10009 m_po_expected_texel_uniform_location = gl.getUniformLocation(m_po_id, "expected_texel");
10010 m_po_lod_uniform_location = gl.getUniformLocation(m_po_id, "lod");
10011
10012 if (m_po_expected_texel_uniform_location == -1)
10013 {
10014 TCU_FAIL("expected_texel is considered an inactive uniform which is invalid");
10015 }
10016
10017 if (m_po_lod_uniform_location == -1)
10018 {
10019 TCU_FAIL("lod is considered an inactive uniform which is invalid");
10020 }
10021 }
10022
10023 /** Initializes all texture objects and all views used by the test. */
initTextures()10024 void TextureViewTestReferenceCounting::initTextures()
10025 {
10026 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
10027
10028 /* Generate texture IDs */
10029 gl.genTextures(1, &m_parent_to_id);
10030 gl.genTextures(1, &m_view_to_id);
10031 gl.genTextures(1, &m_view_view_to_id);
10032 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call(s) failed");
10033
10034 /* Set up parent texture object A */
10035 gl.bindTexture(GL_TEXTURE_2D, m_parent_to_id);
10036 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
10037
10038 gl.texStorage2D(GL_TEXTURE_2D, m_texture_n_levels, GL_RGBA8, m_texture_width, m_texture_height);
10039 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed");
10040
10041 /* Set up view B */
10042 gl.textureView(m_view_to_id, GL_TEXTURE_2D, m_parent_to_id, GL_RGBA8, 0, /* minlevel */
10043 m_texture_n_levels, 0, /* minlayer */
10044 1); /* numlayers */
10045 GLU_EXPECT_NO_ERROR(gl.getError(), "glTextureView() call failed");
10046
10047 /* Set up view C */
10048 gl.textureView(m_view_view_to_id, GL_TEXTURE_2D, m_view_to_id, GL_RGBA8, 0, /* minlevel */
10049 m_texture_n_levels, 0, /* minlayer */
10050 1); /* numlayers */
10051 GLU_EXPECT_NO_ERROR(gl.getError(), "glTextureView() call failed");
10052
10053 /* Fill parent texture mip-maps with different static colors */
10054 unsigned char *texel_data = new unsigned char[m_texture_width * m_texture_height * 4 /* components */];
10055
10056 for (unsigned int n_mipmap = 0; n_mipmap < m_mipmap_colors.size(); n_mipmap++)
10057 {
10058 const _norm_vec4 &mipmap_color = m_mipmap_colors[n_mipmap];
10059 const unsigned int mipmap_height = m_texture_height >> n_mipmap;
10060 const unsigned int mipmap_width = m_texture_width >> n_mipmap;
10061
10062 for (unsigned int n_texel = 0; n_texel < mipmap_height * mipmap_width; ++n_texel)
10063 {
10064 unsigned char *texel_data_ptr = texel_data + n_texel * sizeof(mipmap_color.rgba);
10065
10066 memcpy(texel_data_ptr, mipmap_color.rgba, sizeof(mipmap_color.rgba));
10067 } /* for (all relevant mip-map texels) */
10068
10069 /* Upload new mip-map contents */
10070 gl.texSubImage2D(GL_TEXTURE_2D, n_mipmap, 0, /* xoffset */
10071 0, /* yoffset */
10072 m_texture_width >> n_mipmap, m_texture_height >> n_mipmap, GL_RGBA, GL_UNSIGNED_BYTE,
10073 texel_data);
10074
10075 if (gl.getError() != GL_NO_ERROR)
10076 {
10077 delete[] texel_data;
10078 texel_data = NULL;
10079
10080 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexSubImage2D() call failed");
10081 }
10082 } /* for (all mip-maps) */
10083
10084 delete[] texel_data;
10085 texel_data = NULL;
10086 }
10087
10088 /* Initialize all GL objects necessary to run the test */
initTest()10089 void TextureViewTestReferenceCounting::initTest()
10090 {
10091 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
10092
10093 /* Initialize all texture objects */
10094 initTextures();
10095
10096 /* Initialize test program object */
10097 initProgram();
10098
10099 /* Initialize XFB */
10100 initXFB();
10101
10102 /* Generate and bind a vertex array object, since we'll be doing a number of
10103 * draw calls later in the test */
10104 gl.genVertexArrays(1, &m_vao_id);
10105 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
10106
10107 gl.bindVertexArray(m_vao_id);
10108 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
10109 }
10110
10111 /** Initializes a buffer object later used for Transform Feedback and binds
10112 * it to both general and indexed Transform Feedback binding points.
10113 **/
initXFB()10114 void TextureViewTestReferenceCounting::initXFB()
10115 {
10116 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
10117
10118 /* Quick checks */
10119 DE_ASSERT(m_po_id != 0);
10120
10121 /* Generate a buffer object we'll use for Transform Feedback */
10122 gl.genBuffers(1, &m_bo_id);
10123 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
10124
10125 /* Set up buffer object storage. We need it to be large enough to hold
10126 * sizeof(glw::GLint) per mipmap level */
10127 const glw::GLint bo_size = (glw::GLint)(sizeof(glw::GLint) * m_mipmap_colors.size());
10128
10129 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id);
10130 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
10131
10132 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_bo_id);
10133 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
10134
10135 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bo_size, DE_NULL, /* data */
10136 GL_STATIC_DRAW);
10137 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
10138 }
10139
10140 /** Executes test iteration.
10141 *
10142 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
10143 */
iterate()10144 tcu::TestNode::IterateResult TextureViewTestReferenceCounting::iterate()
10145 {
10146 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
10147
10148 /* Carry on only if GL_ARB_texture_view extension is supported */
10149 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_texture_view"))
10150 {
10151 throw tcu::NotSupportedError("GL_ARB_texture_view is not supported");
10152 }
10153
10154 /* Initialize all GL objects used for the test */
10155 initTest();
10156
10157 /* Make sure texture unit 0 is currently active */
10158 gl.activeTexture(GL_TEXTURE0);
10159 GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture() call failed.");
10160
10161 /* Activate the test program object */
10162 gl.useProgram(m_po_id);
10163 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
10164
10165 /* Run the test in three iterations:
10166 *
10167 * - Sample both the texture and all the views; once that's finished
10168 * successfully, delete the parent texture.
10169 * - Sample both views; once that's finished successfully, delete
10170 * the first of the views;
10171 * - Sample the only remaining view and make sure all mip-maps store
10172 * valid colors.
10173 **/
10174 for (unsigned int n_iteration = 0; n_iteration < 3; /* iterations in total */
10175 n_iteration++)
10176 {
10177 glw::GLuint to_ids_to_sample[3] = {0, 0, 0};
10178
10179 /* Configure IDs of textures we need to validate for current iteration */
10180 switch (n_iteration)
10181 {
10182 case 0:
10183 {
10184 to_ids_to_sample[0] = m_parent_to_id;
10185 to_ids_to_sample[1] = m_view_to_id;
10186 to_ids_to_sample[2] = m_view_view_to_id;
10187
10188 break;
10189 }
10190
10191 case 1:
10192 {
10193 to_ids_to_sample[0] = m_view_to_id;
10194 to_ids_to_sample[1] = m_view_view_to_id;
10195
10196 break;
10197 }
10198
10199 case 2:
10200 {
10201 to_ids_to_sample[0] = m_view_view_to_id;
10202
10203 break;
10204 }
10205
10206 default:
10207 TCU_FAIL("Invalid iteration index");
10208 } /* switch (n_iteration) */
10209
10210 /* Iterate through all texture objects of our concern */
10211 for (unsigned int n_texture = 0; n_texture < sizeof(to_ids_to_sample) / sizeof(to_ids_to_sample[0]);
10212 n_texture++)
10213 {
10214 glw::GLint to_id = to_ids_to_sample[n_texture];
10215
10216 if (to_id == 0)
10217 {
10218 /* No texture object to sample from. */
10219 continue;
10220 }
10221
10222 /* Bind the texture object of our interest to GL_TEXTURE_2D */
10223 gl.bindTexture(GL_TEXTURE_2D, to_id);
10224 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
10225
10226 /* Start XFB */
10227 gl.beginTransformFeedback(GL_POINTS);
10228 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
10229
10230 /* Iterate through all mip-maps of the texture we're currently sampling */
10231 for (unsigned int n_mipmap = 0; n_mipmap < m_mipmap_colors.size(); ++n_mipmap)
10232 {
10233 const _norm_vec4 &expected_mipmap_color = m_mipmap_colors[n_mipmap];
10234
10235 /* Update uniforms first */
10236 gl.uniform4f(m_po_expected_texel_uniform_location, (float)(expected_mipmap_color.rgba[0]) / 255.0f,
10237 (float)(expected_mipmap_color.rgba[1]) / 255.0f,
10238 (float)(expected_mipmap_color.rgba[2]) / 255.0f,
10239 (float)(expected_mipmap_color.rgba[3]) / 255.0f);
10240 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4f() call failed.");
10241
10242 gl.uniform1i(m_po_lod_uniform_location, n_mipmap);
10243 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i() call failed.");
10244
10245 /* Draw a single point. That'll feed the XFB buffer object with a single bool
10246 * indicating if the test passed for the mip-map, or not */
10247 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
10248 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
10249 } /* for (all mip-maps) */
10250
10251 /* We're done - close XFB */
10252 gl.endTransformFeedback();
10253 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
10254
10255 /* How did the sampling go? Map the buffer object containing the run
10256 * results into process space.
10257 */
10258 const glw::GLint *run_results_ptr =
10259 (const glw::GLint *)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
10260
10261 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
10262
10263 if (run_results_ptr == NULL)
10264 {
10265 TCU_FAIL("Pointer to mapped buffer object storage is NULL.");
10266 }
10267
10268 /* Make sure all mip-maps were sampled successfully */
10269 for (unsigned int n_mipmap = 0; n_mipmap < m_mipmap_colors.size(); ++n_mipmap)
10270 {
10271 if (run_results_ptr[n_mipmap] != 1)
10272 {
10273 /* Make sure the TF BO is unmapped before we throw the exception */
10274 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
10275
10276 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid data was sampled for mip-map level ["
10277 << n_mipmap << "] and iteration [" << n_iteration << "]"
10278 << tcu::TestLog::EndMessage;
10279
10280 TCU_FAIL("Mip-map sampling failed.");
10281 }
10282 } /* for (all mip-maps) */
10283
10284 /* Good to unmap the buffer object at this point */
10285 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
10286 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
10287 } /* for (all initialized texture objects) */
10288
10289 /* Now that we're done with the iteration, we should delete iteration-specific texture
10290 * object.
10291 */
10292 switch (n_iteration)
10293 {
10294 case 0:
10295 {
10296 gl.deleteTextures(1, &m_parent_to_id);
10297 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures() call failed.");
10298
10299 m_parent_to_id = 0;
10300 break;
10301 }
10302
10303 case 1:
10304 {
10305 gl.deleteTextures(1, &m_view_to_id);
10306 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures() call failed.");
10307
10308 m_view_to_id = 0;
10309 break;
10310 }
10311
10312 case 2:
10313 {
10314 gl.deleteTextures(1, &m_view_view_to_id);
10315 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures() call failed.");
10316
10317 m_view_view_to_id = 0;
10318 break;
10319 }
10320
10321 default:
10322 TCU_FAIL("Invalid iteration index");
10323 } /* switch (n_iteration) */
10324 } /* for (all iterations) */
10325
10326 /* Test case passed */
10327 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
10328
10329 return STOP;
10330 }
10331
10332 /** Constructor.
10333 *
10334 * @param context Rendering context.
10335 **/
TextureViewTests(deqp::Context & context)10336 TextureViewTests::TextureViewTests(deqp::Context &context)
10337 : TestCaseGroup(context, "texture_view", "Verifies \"texture view\" functionality")
10338 {
10339 /* Left blank on purpose */
10340 }
10341
10342 /** Initializes a texture_storage_multisample test group.
10343 *
10344 **/
init(void)10345 void TextureViewTests::init(void)
10346 {
10347 addChild(new TextureViewTestGetTexParameter(m_context));
10348 addChild(new TextureViewTestErrors(m_context));
10349 addChild(new TextureViewTestViewSampling(m_context));
10350 addChild(new TextureViewTestViewClasses(m_context));
10351 addChild(new TextureViewTestCoherency(m_context));
10352 addChild(new TextureViewTestBaseAndMaxLevels(m_context));
10353 addChild(new TextureViewTestReferenceCounting(m_context));
10354 }
10355
10356 } // namespace gl4cts
10357