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