• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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