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