• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2015-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  gl4cMultiBindTests.cpp
26  * \brief Implements conformance tests for "Multi Bind" functionality.
27  */ /*-------------------------------------------------------------------*/
28 
29 #include "gl4cMultiBindTests.hpp"
30 
31 #include "gluDefs.hpp"
32 #include "gluStrUtil.hpp"
33 #include "glwEnums.hpp"
34 #include "glwFunctions.hpp"
35 #include "tcuTestLog.hpp"
36 
37 #include <string>
38 
39 #define DEBUG_ENBALE_MESSAGE_CALLBACK 0
40 
41 #if DEBUG_ENBALE_MESSAGE_CALLBACK
42 #include <iomanip>
43 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
44 
45 using namespace glw;
46 
47 namespace gl4cts
48 {
49 namespace MultiBind
50 {
51 
52 #if DEBUG_ENBALE_MESSAGE_CALLBACK
53 /** Debuging procedure. Logs parameters.
54  *
55  * @param source   As specified in GL spec.
56  * @param type     As specified in GL spec.
57  * @param id       As specified in GL spec.
58  * @param severity As specified in GL spec.
59  * @param ignored
60  * @param message  As specified in GL spec.
61  * @param info     Pointer to instance of deqp::Context used by test.
62  */
debug_proc(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei,const GLchar * message,void * info)63 void GLW_APIENTRY debug_proc(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei /* length */,
64 							 const GLchar* message, void* info)
65 {
66 	deqp::Context* ctx = (deqp::Context*)info;
67 
68 	const GLchar* source_str   = "Unknown";
69 	const GLchar* type_str	 = "Unknown";
70 	const GLchar* severity_str = "Unknown";
71 
72 	switch (source)
73 	{
74 	case GL_DEBUG_SOURCE_API:
75 		source_str = "API";
76 		break;
77 	case GL_DEBUG_SOURCE_APPLICATION:
78 		source_str = "APP";
79 		break;
80 	case GL_DEBUG_SOURCE_OTHER:
81 		source_str = "OTR";
82 		break;
83 	case GL_DEBUG_SOURCE_SHADER_COMPILER:
84 		source_str = "COM";
85 		break;
86 	case GL_DEBUG_SOURCE_THIRD_PARTY:
87 		source_str = "3RD";
88 		break;
89 	case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
90 		source_str = "WS";
91 		break;
92 	default:
93 		break;
94 	}
95 
96 	switch (type)
97 	{
98 	case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
99 		type_str = "DEPRECATED_BEHAVIOR";
100 		break;
101 	case GL_DEBUG_TYPE_ERROR:
102 		type_str = "ERROR";
103 		break;
104 	case GL_DEBUG_TYPE_MARKER:
105 		type_str = "MARKER";
106 		break;
107 	case GL_DEBUG_TYPE_OTHER:
108 		type_str = "OTHER";
109 		break;
110 	case GL_DEBUG_TYPE_PERFORMANCE:
111 		type_str = "PERFORMANCE";
112 		break;
113 	case GL_DEBUG_TYPE_POP_GROUP:
114 		type_str = "POP_GROUP";
115 		break;
116 	case GL_DEBUG_TYPE_PORTABILITY:
117 		type_str = "PORTABILITY";
118 		break;
119 	case GL_DEBUG_TYPE_PUSH_GROUP:
120 		type_str = "PUSH_GROUP";
121 		break;
122 	case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
123 		type_str = "UNDEFINED_BEHAVIOR";
124 		break;
125 	default:
126 		break;
127 	}
128 
129 	switch (severity)
130 	{
131 	case GL_DEBUG_SEVERITY_HIGH:
132 		severity_str = "H";
133 		break;
134 	case GL_DEBUG_SEVERITY_LOW:
135 		severity_str = "L";
136 		break;
137 	case GL_DEBUG_SEVERITY_MEDIUM:
138 		severity_str = "M";
139 		break;
140 	case GL_DEBUG_SEVERITY_NOTIFICATION:
141 		severity_str = "N";
142 		break;
143 	default:
144 		break;
145 	}
146 
147 	ctx->getTestContext().getLog() << tcu::TestLog::Message << "DEBUG_INFO: " << std::setw(3) << source_str << "|"
148 								   << severity_str << "|" << std::setw(18) << type_str << "|" << std::setw(12) << id
149 								   << ": " << message << tcu::TestLog::EndMessage;
150 }
151 
152 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
153 
154 /** Represents buffer instance
155  * Provides basic buffer functionality
156  **/
157 class Buffer
158 {
159 public:
160 	/* Public methods */
161 	/* Ctr & Dtr */
162 	Buffer();
163 	~Buffer();
164 
165 	/* Init & Release */
166 	void Init(deqp::Context& context);
167 
168 	void InitData(deqp::Context& context, glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size,
169 				  const glw::GLvoid* data);
170 
171 	void Release();
172 
173 	/* Functionality */
174 	void Bind() const;
175 	void BindBase(glw::GLuint index) const;
176 
177 	/* Public static routines */
178 	/* Functionality */
179 	static void Bind(const glw::Functions& gl, glw::GLuint id, glw::GLenum target);
180 
181 	static void BindBase(const glw::Functions& gl, glw::GLuint id, glw::GLenum target, glw::GLuint index);
182 
183 	static void Data(const glw::Functions& gl, glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size,
184 					 const glw::GLvoid* data);
185 
186 	static void Generate(const glw::Functions& gl, glw::GLuint& out_id);
187 
188 	static void SubData(const glw::Functions& gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr size,
189 						glw::GLvoid* data);
190 
191 	/* Public fields */
192 	glw::GLuint m_id;
193 
194 	/* Public constants */
195 	static const glw::GLuint m_invalid_id;
196 
197 private:
198 	/* Private enums */
199 
200 	/* Private fields */
201 	deqp::Context* m_context;
202 	glw::GLenum	m_target;
203 };
204 
205 /** Represents framebuffer
206  * Provides basic functionality
207  **/
208 class Framebuffer
209 {
210 public:
211 	/* Public methods */
212 	/* Ctr & Dtr */
213 	Framebuffer(deqp::Context& context);
214 	~Framebuffer();
215 
216 	/* Init & Release */
217 	void Release();
218 
219 	/* Public static routines */
220 	static void AttachTexture(const glw::Functions& gl, glw::GLenum target, glw::GLenum attachment,
221 							  glw::GLuint texture_id, glw::GLint level, glw::GLuint width, glw::GLuint height);
222 
223 	static void Bind(const glw::Functions& gl, glw::GLenum target, glw::GLuint id);
224 
225 	static void Generate(const glw::Functions& gl, glw::GLuint& out_id);
226 
227 	/* Public fields */
228 	glw::GLuint m_id;
229 
230 	/* Public constants */
231 	static const glw::GLuint m_invalid_id;
232 
233 private:
234 	/* Private fields */
235 	deqp::Context& m_context;
236 };
237 
238 /** Represents shader instance.
239  * Provides basic functionality for shaders.
240  **/
241 class Shader
242 {
243 public:
244 	/* Public methods */
245 	/* Ctr & Dtr */
246 	Shader(deqp::Context& context);
247 	~Shader();
248 
249 	/* Init & Realese */
250 	void Init(glw::GLenum stage, const std::string& source);
251 	void Release();
252 
253 	/* Public static routines */
254 	/* Functionality */
255 	static void Compile(const glw::Functions& gl, glw::GLuint id);
256 
257 	static void Create(const glw::Functions& gl, glw::GLenum stage, glw::GLuint& out_id);
258 
259 	static void Source(const glw::Functions& gl, glw::GLuint id, const std::string& source);
260 
261 	/* Public fields */
262 	glw::GLuint m_id;
263 
264 	/* Public constants */
265 	static const glw::GLuint m_invalid_id;
266 
267 private:
268 	/* Private fields */
269 	deqp::Context& m_context;
270 };
271 
272 /** Represents program instance.
273  * Provides basic functionality
274  **/
275 class Program
276 {
277 public:
278 	/* Public methods */
279 	/* Ctr & Dtr */
280 	Program(deqp::Context& context);
281 	~Program();
282 
283 	/* Init & Release */
284 	void Init(const std::string& compute_shader, const std::string& fragment_shader, const std::string& geometry_shader,
285 			  const std::string& tesselation_control_shader, const std::string& tesselation_evaluation_shader,
286 			  const std::string& vertex_shader);
287 	void Release();
288 
289 	/* Functionality */
290 	void Use() const;
291 
292 	/* Public static routines */
293 	/* Functionality */
294 	static void Attach(const glw::Functions& gl, glw::GLuint program_id, glw::GLuint shader_id);
295 
296 	static void Create(const glw::Functions& gl, glw::GLuint& out_id);
297 
298 	static void Link(const glw::Functions& gl, glw::GLuint id);
299 
300 	static void Use(const glw::Functions& gl, glw::GLuint id);
301 
302 	/* Public fields */
303 	glw::GLuint m_id;
304 
305 	Shader m_compute;
306 	Shader m_fragment;
307 	Shader m_geometry;
308 	Shader m_tess_ctrl;
309 	Shader m_tess_eval;
310 	Shader m_vertex;
311 
312 	/* Public constants */
313 	static const glw::GLuint m_invalid_id;
314 
315 private:
316 	/* Private fields */
317 	deqp::Context& m_context;
318 };
319 
320 /** Represents texture instance
321  **/
322 class Texture
323 {
324 public:
325 	/* Public methods */
326 	/* Ctr & Dtr */
327 	Texture();
328 	~Texture();
329 
330 	/* Init & Release */
331 	void Init(deqp::Context& context);
332 
333 	void InitBuffer(deqp::Context& context, glw::GLenum internal_format, glw::GLuint buffer_id);
334 
335 	void InitStorage(deqp::Context& context, glw::GLenum target, glw::GLsizei levels, glw::GLenum internal_format,
336 					 glw::GLuint width, glw::GLuint height, glw::GLuint depth, bool allow_error = false);
337 
338 	void Release();
339 
340 	/* Public static routines */
341 	/* Functionality */
342 	static void Bind(const glw::Functions& gl, glw::GLuint id, glw::GLenum target);
343 
344 	static void CompressedImage(const glw::Functions& gl, glw::GLenum target, glw::GLint level,
345 								glw::GLenum internal_format, glw::GLuint width, glw::GLuint height, glw::GLuint depth,
346 								glw::GLsizei image_size, const glw::GLvoid* data);
347 
348 	static void Generate(const glw::Functions& gl, glw::GLuint& out_id);
349 
350 	static void GetData(const glw::Functions& gl, glw::GLint level, glw::GLenum target, glw::GLenum format,
351 						glw::GLenum type, glw::GLvoid* out_data);
352 
353 	static void GetLevelParameter(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLenum pname,
354 								  glw::GLint* param);
355 
356 	static void Image(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLenum internal_format,
357 					  glw::GLuint width, glw::GLuint height, glw::GLuint depth, glw::GLenum format, glw::GLenum type,
358 					  const glw::GLvoid* data);
359 
360 	static void Storage(const glw::Functions& gl, glw::GLenum target, glw::GLsizei levels, glw::GLenum internal_format,
361 						glw::GLuint width, glw::GLuint height, glw::GLuint depth, bool allow_error);
362 
363 	static void SubImage(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLint x, glw::GLint y,
364 						 glw::GLint z, glw::GLsizei width, glw::GLsizei height, glw::GLsizei depth, glw::GLenum format,
365 						 glw::GLenum type, const glw::GLvoid* pixels);
366 
367 	/* Public fields */
368 	glw::GLuint m_id;
369 
370 	/* Public constants */
371 	static const glw::GLuint m_invalid_id;
372 
373 private:
374 	/* Private fields */
375 	deqp::Context* m_context;
376 };
377 
378 /* Buffer constants */
379 const GLuint Buffer::m_invalid_id = -1;
380 
381 /** Constructor.
382  *
383  **/
Buffer()384 Buffer::Buffer() : m_id(m_invalid_id), m_context(0), m_target(GL_ARRAY_BUFFER)
385 {
386 }
387 
388 /** Destructor
389  *
390  **/
~Buffer()391 Buffer::~Buffer()
392 {
393 	Release();
394 
395 	m_context = 0;
396 }
397 
398 /** Initialize buffer instance
399  *
400  * @param context CTS context.
401  **/
Init(deqp::Context & context)402 void Buffer::Init(deqp::Context& context)
403 {
404 	Release();
405 
406 	m_context = &context;
407 }
408 
409 /** Initialize buffer instance with some data
410  *
411  * @param context CTS context.
412  * @param target Buffer target
413  * @param usage  Buffer usage enum
414  * @param size   <size> parameter
415  * @param data   <data> parameter
416  **/
InitData(deqp::Context & context,glw::GLenum target,glw::GLenum usage,glw::GLsizeiptr size,const glw::GLvoid * data)417 void Buffer::InitData(deqp::Context& context, glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size,
418 					  const glw::GLvoid* data)
419 {
420 	Init(context);
421 
422 	m_target = target;
423 
424 	const Functions& gl = m_context->getRenderContext().getFunctions();
425 
426 	Generate(gl, m_id);
427 	Bind(gl, m_id, m_target);
428 	Data(gl, m_target, usage, size, data);
429 }
430 
431 /** Release buffer instance
432  *
433  **/
Release()434 void Buffer::Release()
435 {
436 	if (m_invalid_id != m_id)
437 	{
438 		const Functions& gl = m_context->getRenderContext().getFunctions();
439 
440 		gl.deleteBuffers(1, &m_id);
441 		m_id = m_invalid_id;
442 	}
443 }
444 
445 /** Binds buffer to its target
446  *
447  **/
Bind() const448 void Buffer::Bind() const
449 {
450 	if (m_invalid_id == m_id)
451 	{
452 		return;
453 	}
454 
455 	const Functions& gl = m_context->getRenderContext().getFunctions();
456 
457 	Bind(gl, m_id, m_target);
458 }
459 
460 /** Binds indexed buffer
461  *
462  * @param index <index> parameter
463  **/
BindBase(glw::GLuint index) const464 void Buffer::BindBase(glw::GLuint index) const
465 {
466 	if (m_invalid_id == m_id)
467 	{
468 		return;
469 	}
470 
471 	const Functions& gl = m_context->getRenderContext().getFunctions();
472 
473 	BindBase(gl, m_id, m_target, index);
474 }
475 
476 /** Bind buffer to given target
477  *
478  * @param gl     GL functions
479  * @param id     Id of buffer
480  * @param target Buffer target
481  **/
Bind(const glw::Functions & gl,glw::GLuint id,glw::GLenum target)482 void Buffer::Bind(const glw::Functions& gl, glw::GLuint id, glw::GLenum target)
483 {
484 	gl.bindBuffer(target, id);
485 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
486 }
487 
488 /** Binds indexed buffer
489  *
490  * @param gl     GL functions
491  * @param id     Id of buffer
492  * @param target Buffer target
493  * @param index  <index> parameter
494  **/
BindBase(const glw::Functions & gl,glw::GLuint id,glw::GLenum target,glw::GLuint index)495 void Buffer::BindBase(const glw::Functions& gl, glw::GLuint id, glw::GLenum target, glw::GLuint index)
496 {
497 	gl.bindBufferBase(target, index, id);
498 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferBase");
499 }
500 
501 /** Allocate memory for buffer and sends initial content
502  *
503  * @param gl     GL functions
504  * @param target Buffer target
505  * @param usage  Buffer usage enum
506  * @param size   <size> parameter
507  * @param data   <data> parameter
508  **/
Data(const glw::Functions & gl,glw::GLenum target,glw::GLenum usage,glw::GLsizeiptr size,const glw::GLvoid * data)509 void Buffer::Data(const glw::Functions& gl, glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size,
510 				  const glw::GLvoid* data)
511 {
512 	gl.bufferData(target, size, data, usage);
513 	GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
514 }
515 
516 /** Generate buffer
517  *
518  * @param gl     GL functions
519  * @param out_id Id of buffer
520  **/
Generate(const glw::Functions & gl,glw::GLuint & out_id)521 void Buffer::Generate(const glw::Functions& gl, glw::GLuint& out_id)
522 {
523 	GLuint id = m_invalid_id;
524 
525 	gl.genBuffers(1, &id);
526 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
527 
528 	if (m_invalid_id == id)
529 	{
530 		TCU_FAIL("Got invalid id");
531 	}
532 
533 	out_id = id;
534 }
535 
536 /** Update range of buffer
537  *
538  * @param gl     GL functions
539  * @param target Buffer target
540  * @param offset Offset in buffer
541  * @param size   <size> parameter
542  * @param data   <data> parameter
543  **/
SubData(const glw::Functions & gl,glw::GLenum target,glw::GLintptr offset,glw::GLsizeiptr size,glw::GLvoid * data)544 void Buffer::SubData(const glw::Functions& gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr size,
545 					 glw::GLvoid* data)
546 {
547 	gl.bufferSubData(target, offset, size, data);
548 	GLU_EXPECT_NO_ERROR(gl.getError(), "BufferSubData");
549 }
550 
551 /* Framebuffer constants */
552 const GLuint Framebuffer::m_invalid_id = -1;
553 
554 /** Constructor.
555  *
556  * @param context CTS context.
557  **/
Framebuffer(deqp::Context & context)558 Framebuffer::Framebuffer(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
559 {
560 	/* Nothing to done here */
561 }
562 
563 /** Destructor
564  *
565  **/
~Framebuffer()566 Framebuffer::~Framebuffer()
567 {
568 	Release();
569 }
570 
571 /** Release texture instance
572  *
573  **/
Release()574 void Framebuffer::Release()
575 {
576 	if (m_invalid_id != m_id)
577 	{
578 		const Functions& gl = m_context.getRenderContext().getFunctions();
579 
580 		gl.deleteFramebuffers(1, &m_id);
581 		m_id = m_invalid_id;
582 	}
583 }
584 
585 /** Attach texture to specified attachment
586  *
587  * @param gl         GL functions
588  * @param target     Framebuffer target
589  * @param attachment Attachment
590  * @param texture_id Texture id
591  * @param level      Level of mipmap
592  * @param width      Texture width
593  * @param height     Texture height
594  **/
AttachTexture(const glw::Functions & gl,glw::GLenum target,glw::GLenum attachment,glw::GLuint texture_id,glw::GLint level,glw::GLuint width,glw::GLuint height)595 void Framebuffer::AttachTexture(const glw::Functions& gl, glw::GLenum target, glw::GLenum attachment,
596 								glw::GLuint texture_id, glw::GLint level, glw::GLuint width, glw::GLuint height)
597 {
598 	gl.framebufferTexture(target, attachment, texture_id, level);
599 	GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture");
600 
601 	gl.viewport(0 /* x */, 0 /* y */, width, height);
602 	GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
603 }
604 
605 /** Binds framebuffer to DRAW_FRAMEBUFFER
606  *
607  * @param gl     GL functions
608  * @param target Framebuffer target
609  * @param id     ID of framebuffer
610  **/
Bind(const glw::Functions & gl,glw::GLenum target,glw::GLuint id)611 void Framebuffer::Bind(const glw::Functions& gl, glw::GLenum target, glw::GLuint id)
612 {
613 	gl.bindFramebuffer(target, id);
614 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
615 }
616 
617 /** Generate framebuffer
618  *
619  **/
Generate(const glw::Functions & gl,glw::GLuint & out_id)620 void Framebuffer::Generate(const glw::Functions& gl, glw::GLuint& out_id)
621 {
622 	GLuint id = m_invalid_id;
623 
624 	gl.genFramebuffers(1, &id);
625 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
626 
627 	if (m_invalid_id == id)
628 	{
629 		TCU_FAIL("Invalid id");
630 	}
631 
632 	out_id = id;
633 }
634 
635 /* Program constants */
636 const GLuint Program::m_invalid_id = 0;
637 
638 /** Constructor.
639  *
640  * @param context CTS context.
641  **/
Program(deqp::Context & context)642 Program::Program(deqp::Context& context)
643 	: m_id(m_invalid_id)
644 	, m_compute(context)
645 	, m_fragment(context)
646 	, m_geometry(context)
647 	, m_tess_ctrl(context)
648 	, m_tess_eval(context)
649 	, m_vertex(context)
650 	, m_context(context)
651 {
652 	/* Nothing to be done here */
653 }
654 
655 /** Destructor
656  *
657  **/
~Program()658 Program::~Program()
659 {
660 	Release();
661 }
662 
663 /** Initialize program instance
664  *
665  * @param compute_shader                Compute shader source code
666  * @param fragment_shader               Fragment shader source code
667  * @param geometry_shader               Geometry shader source code
668  * @param tesselation_control_shader    Tesselation control shader source code
669  * @param tesselation_evaluation_shader Tesselation evaluation shader source code
670  * @param vertex_shader                 Vertex shader source code
671  **/
Init(const std::string & compute_shader,const std::string & fragment_shader,const std::string & geometry_shader,const std::string & tesselation_control_shader,const std::string & tesselation_evaluation_shader,const std::string & vertex_shader)672 void Program::Init(const std::string& compute_shader, const std::string& fragment_shader,
673 				   const std::string& geometry_shader, const std::string& tesselation_control_shader,
674 				   const std::string& tesselation_evaluation_shader, const std::string& vertex_shader)
675 {
676 	/* Delete previous program */
677 	Release();
678 
679 	/* GL entry points */
680 	const Functions& gl = m_context.getRenderContext().getFunctions();
681 
682 	/* Initialize shaders */
683 	m_compute.Init(GL_COMPUTE_SHADER, compute_shader);
684 	m_fragment.Init(GL_FRAGMENT_SHADER, fragment_shader);
685 	m_geometry.Init(GL_GEOMETRY_SHADER, geometry_shader);
686 	m_tess_ctrl.Init(GL_TESS_CONTROL_SHADER, tesselation_control_shader);
687 	m_tess_eval.Init(GL_TESS_EVALUATION_SHADER, tesselation_evaluation_shader);
688 	m_vertex.Init(GL_VERTEX_SHADER, vertex_shader);
689 
690 	/* Create program, set up transform feedback and attach shaders */
691 	Create(gl, m_id);
692 	Attach(gl, m_id, m_compute.m_id);
693 	Attach(gl, m_id, m_fragment.m_id);
694 	Attach(gl, m_id, m_geometry.m_id);
695 	Attach(gl, m_id, m_tess_ctrl.m_id);
696 	Attach(gl, m_id, m_tess_eval.m_id);
697 	Attach(gl, m_id, m_vertex.m_id);
698 
699 	/* Link program */
700 	Link(gl, m_id);
701 }
702 
703 /** Release program instance
704  *
705  **/
Release()706 void Program::Release()
707 {
708 	const Functions& gl = m_context.getRenderContext().getFunctions();
709 
710 	if (m_invalid_id != m_id)
711 	{
712 		Use(gl, m_invalid_id);
713 
714 		gl.deleteProgram(m_id);
715 		m_id = m_invalid_id;
716 	}
717 
718 	m_compute.Release();
719 	m_fragment.Release();
720 	m_geometry.Release();
721 	m_tess_ctrl.Release();
722 	m_tess_eval.Release();
723 	m_vertex.Release();
724 }
725 
726 /** Set program as active
727  *
728  **/
Use() const729 void Program::Use() const
730 {
731 	const Functions& gl = m_context.getRenderContext().getFunctions();
732 
733 	Use(gl, m_id);
734 }
735 
736 /** Attach shader to program
737  *
738  * @param gl         GL functions
739  * @param program_id Id of program
740  * @param shader_id  Id of shader
741  **/
Attach(const glw::Functions & gl,glw::GLuint program_id,glw::GLuint shader_id)742 void Program::Attach(const glw::Functions& gl, glw::GLuint program_id, glw::GLuint shader_id)
743 {
744 	/* Sanity checks */
745 	if ((m_invalid_id == program_id) || (Shader::m_invalid_id == shader_id))
746 	{
747 		return;
748 	}
749 
750 	gl.attachShader(program_id, shader_id);
751 	GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
752 }
753 
754 /** Create program instance
755  *
756  * @param gl     GL functions
757  * @param out_id Id of program
758  **/
Create(const glw::Functions & gl,glw::GLuint & out_id)759 void Program::Create(const glw::Functions& gl, glw::GLuint& out_id)
760 {
761 	const GLuint id = gl.createProgram();
762 	GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
763 
764 	if (m_invalid_id == id)
765 	{
766 		TCU_FAIL("Failed to create program");
767 	}
768 
769 	out_id = id;
770 }
771 
772 /** Link program
773  *
774  * @param gl GL functions
775  * @param id Id of program
776  **/
Link(const glw::Functions & gl,glw::GLuint id)777 void Program::Link(const glw::Functions& gl, glw::GLuint id)
778 {
779 	GLint status = GL_FALSE;
780 
781 	gl.linkProgram(id);
782 	GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram");
783 
784 	/* Get link status */
785 	gl.getProgramiv(id, GL_LINK_STATUS, &status);
786 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
787 
788 	/* Log link error */
789 	if (GL_TRUE != status)
790 	{
791 		glw::GLint  length = 0;
792 		std::string message;
793 
794 		/* Get error log length */
795 		gl.getProgramiv(id, GL_INFO_LOG_LENGTH, &length);
796 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
797 
798 		message.resize(length, 0);
799 
800 		/* Get error log */
801 		gl.getProgramInfoLog(id, length, 0, &message[0]);
802 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog");
803 
804 		TCU_FAIL(message.c_str());
805 	}
806 }
807 
808 /** Use program
809  *
810  * @param gl GL functions
811  * @param id Id of program
812  **/
Use(const glw::Functions & gl,glw::GLuint id)813 void Program::Use(const glw::Functions& gl, glw::GLuint id)
814 {
815 	gl.useProgram(id);
816 	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
817 }
818 
819 /* Shader's constants */
820 const GLuint Shader::m_invalid_id = 0;
821 
822 /** Constructor.
823  *
824  * @param context CTS context.
825  **/
Shader(deqp::Context & context)826 Shader::Shader(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
827 {
828 	/* Nothing to be done here */
829 }
830 
831 /** Destructor
832  *
833  **/
~Shader()834 Shader::~Shader()
835 {
836 	Release();
837 }
838 
839 /** Initialize shader instance
840  *
841  * @param stage  Shader stage
842  * @param source Source code
843  **/
Init(glw::GLenum stage,const std::string & source)844 void Shader::Init(glw::GLenum stage, const std::string& source)
845 {
846 	if (true == source.empty())
847 	{
848 		/* No source == no shader */
849 		return;
850 	}
851 
852 	/* Delete any previous shader */
853 	Release();
854 
855 	/* Create, set source and compile */
856 	const Functions& gl = m_context.getRenderContext().getFunctions();
857 
858 	Create(gl, stage, m_id);
859 	Source(gl, m_id, source);
860 
861 	Compile(gl, m_id);
862 }
863 
864 /** Release shader instance
865  *
866  **/
Release()867 void Shader::Release()
868 {
869 	if (m_invalid_id != m_id)
870 	{
871 		const Functions& gl = m_context.getRenderContext().getFunctions();
872 
873 		gl.deleteShader(m_id);
874 		m_id = m_invalid_id;
875 	}
876 }
877 
878 /** Compile shader
879  *
880  * @param gl GL functions
881  * @param id Shader id
882  **/
Compile(const glw::Functions & gl,glw::GLuint id)883 void Shader::Compile(const glw::Functions& gl, glw::GLuint id)
884 {
885 	GLint status = GL_FALSE;
886 
887 	/* Compile */
888 	gl.compileShader(id);
889 	GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader");
890 
891 	/* Get compilation status */
892 	gl.getShaderiv(id, GL_COMPILE_STATUS, &status);
893 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
894 
895 	/* Log compilation error */
896 	if (GL_TRUE != status)
897 	{
898 		glw::GLint  length = 0;
899 		std::string message;
900 
901 		/* Error log length */
902 		gl.getShaderiv(id, GL_INFO_LOG_LENGTH, &length);
903 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
904 
905 		/* Prepare storage */
906 		message.resize(length, 0);
907 
908 		/* Get error log */
909 		gl.getShaderInfoLog(id, length, 0, &message[0]);
910 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog");
911 
912 		TCU_FAIL(message.c_str());
913 	}
914 }
915 
916 /** Create shader
917  *
918  * @param gl     GL functions
919  * @param stage  Shader stage
920  * @param out_id Shader id
921  **/
Create(const glw::Functions & gl,glw::GLenum stage,glw::GLuint & out_id)922 void Shader::Create(const glw::Functions& gl, glw::GLenum stage, glw::GLuint& out_id)
923 {
924 	const GLuint id = gl.createShader(stage);
925 	GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
926 
927 	if (m_invalid_id == id)
928 	{
929 		TCU_FAIL("Failed to create shader");
930 	}
931 
932 	out_id = id;
933 }
934 
935 /** Set shader's source code
936  *
937  * @param gl     GL functions
938  * @param id     Shader id
939  * @param source Shader source code
940  **/
Source(const glw::Functions & gl,glw::GLuint id,const std::string & source)941 void Shader::Source(const glw::Functions& gl, glw::GLuint id, const std::string& source)
942 {
943 	const GLchar* code = source.c_str();
944 
945 	gl.shaderSource(id, 1 /* count */, &code, 0 /* lengths */);
946 	GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource");
947 }
948 
949 /* Texture static fields */
950 const GLuint Texture::m_invalid_id = -1;
951 
952 /** Constructor.
953  *
954  **/
Texture()955 Texture::Texture() : m_id(m_invalid_id), m_context(0)
956 {
957 	/* Nothing to done here */
958 }
959 
960 /** Destructor
961  *
962  **/
~Texture()963 Texture::~Texture()
964 {
965 	Release();
966 }
967 
968 /** Initialize texture instance
969  *
970  * @param context Test context
971  **/
Init(deqp::Context & context)972 void Texture::Init(deqp::Context& context)
973 {
974 	Release();
975 
976 	m_context = &context;
977 }
978 
979 /** Initialize texture instance as texture buffer
980  *
981  * @param context         Test context
982  * @param internal_format Internal format of texture
983  * @param buufer_id       ID of buffer that will be used as storage
984  **/
InitBuffer(deqp::Context & context,glw::GLenum internal_format,glw::GLuint buffer_id)985 void Texture::InitBuffer(deqp::Context& context, glw::GLenum internal_format, glw::GLuint buffer_id)
986 {
987 	Init(context);
988 
989 	const Functions& gl = m_context->getRenderContext().getFunctions();
990 
991 	Generate(gl, m_id);
992 	Bind(gl, m_id, GL_TEXTURE_BUFFER);
993 	Buffer::Bind(gl, buffer_id, GL_TEXTURE_BUFFER);
994 
995 	gl.texBuffer(GL_TEXTURE_BUFFER, internal_format, buffer_id);
996 	GLU_EXPECT_NO_ERROR(gl.getError(), "TexBuffer");
997 }
998 
999 /** Initialize texture instance with storage
1000  *
1001  * @param context         Test context
1002  * @param target          Texture target
1003  * @param levels          Number of levels
1004  * @param internal_format Internal format of texture
1005  * @param width           Width of texture
1006  * @param height          Height of texture
1007  * @param depth           Depth of texture
1008  **/
InitStorage(deqp::Context & context,glw::GLenum target,glw::GLsizei levels,glw::GLenum internal_format,glw::GLuint width,glw::GLuint height,glw::GLuint depth,bool allow_error)1009 void Texture::InitStorage(deqp::Context& context, glw::GLenum target, glw::GLsizei levels, glw::GLenum internal_format,
1010 						  glw::GLuint width, glw::GLuint height, glw::GLuint depth, bool allow_error)
1011 {
1012 	Init(context);
1013 
1014 	const Functions& gl = m_context->getRenderContext().getFunctions();
1015 
1016 	Generate(gl, m_id);
1017 	Bind(gl, m_id, target);
1018 	Storage(gl, target, levels, internal_format, width, height, depth, allow_error);
1019 }
1020 
1021 /** Release texture instance
1022  *
1023  * @param context CTS context.
1024  **/
Release()1025 void Texture::Release()
1026 {
1027 	if (m_invalid_id != m_id)
1028 	{
1029 		const Functions& gl = m_context->getRenderContext().getFunctions();
1030 
1031 		gl.deleteTextures(1, &m_id);
1032 		m_id = m_invalid_id;
1033 	}
1034 }
1035 
1036 /** Bind texture to target
1037  *
1038  * @param gl       GL functions
1039  * @param id       Id of texture
1040  * @param tex_type Type of texture
1041  **/
Bind(const glw::Functions & gl,glw::GLuint id,glw::GLenum target)1042 void Texture::Bind(const glw::Functions& gl, glw::GLuint id, glw::GLenum target)
1043 {
1044 	gl.bindTexture(target, id);
1045 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
1046 }
1047 
1048 /** Set contents of compressed texture
1049  *
1050  * @param gl              GL functions
1051  * @param target          Texture target
1052  * @param level           Mipmap level
1053  * @param internal_format Format of data
1054  * @param width           Width of texture
1055  * @param height          Height of texture
1056  * @param depth           Depth of texture
1057  * @param image_size      Size of data
1058  * @param data            Buffer with image data
1059  **/
CompressedImage(const glw::Functions & gl,glw::GLenum target,glw::GLint level,glw::GLenum internal_format,glw::GLuint width,glw::GLuint height,glw::GLuint depth,glw::GLsizei image_size,const glw::GLvoid * data)1060 void Texture::CompressedImage(const glw::Functions& gl, glw::GLenum target, glw::GLint level,
1061 							  glw::GLenum internal_format, glw::GLuint width, glw::GLuint height, glw::GLuint depth,
1062 							  glw::GLsizei image_size, const glw::GLvoid* data)
1063 {
1064 	switch (target)
1065 	{
1066 	case GL_TEXTURE_1D:
1067 		gl.compressedTexImage1D(target, level, internal_format, width, 0 /* border */, image_size, data);
1068 		GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage1D");
1069 		break;
1070 	case GL_TEXTURE_1D_ARRAY:
1071 	case GL_TEXTURE_2D:
1072 	case GL_TEXTURE_RECTANGLE:
1073 		gl.compressedTexImage2D(target, level, internal_format, width, height, 0 /* border */, image_size, data);
1074 		GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage2D");
1075 		break;
1076 	case GL_TEXTURE_CUBE_MAP:
1077 		gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, internal_format, width, height, 0 /* border */,
1078 								image_size, data);
1079 		gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, internal_format, width, height, 0 /* border */,
1080 								image_size, data);
1081 		gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, internal_format, width, height, 0 /* border */,
1082 								image_size, data);
1083 		gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, internal_format, width, height, 0 /* border */,
1084 								image_size, data);
1085 		gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, internal_format, width, height, 0 /* border */,
1086 								image_size, data);
1087 		gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, internal_format, width, height, 0 /* border */,
1088 								image_size, data);
1089 		GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage2D");
1090 		break;
1091 	case GL_TEXTURE_3D:
1092 	case GL_TEXTURE_2D_ARRAY:
1093 		gl.compressedTexImage3D(target, level, internal_format, width, height, depth, 0 /* border */, image_size, data);
1094 		GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage3D");
1095 		break;
1096 	default:
1097 		TCU_FAIL("Invliad enum");
1098 	}
1099 }
1100 
1101 /** Generate texture instance
1102  *
1103  * @param gl     GL functions
1104  * @param out_id Id of texture
1105  **/
Generate(const glw::Functions & gl,glw::GLuint & out_id)1106 void Texture::Generate(const glw::Functions& gl, glw::GLuint& out_id)
1107 {
1108 	GLuint id = m_invalid_id;
1109 
1110 	gl.genTextures(1, &id);
1111 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
1112 
1113 	if (m_invalid_id == id)
1114 	{
1115 		TCU_FAIL("Invalid id");
1116 	}
1117 
1118 	out_id = id;
1119 }
1120 
1121 /** Get texture data
1122  *
1123  * @param gl       GL functions
1124  * @param target   Texture target
1125  * @param format   Format of data
1126  * @param type     Type of data
1127  * @param out_data Buffer for data
1128  **/
GetData(const glw::Functions & gl,glw::GLint level,glw::GLenum target,glw::GLenum format,glw::GLenum type,glw::GLvoid * out_data)1129 void Texture::GetData(const glw::Functions& gl, glw::GLint level, glw::GLenum target, glw::GLenum format,
1130 					  glw::GLenum type, glw::GLvoid* out_data)
1131 {
1132 	gl.getTexImage(target, level, format, type, out_data);
1133 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
1134 }
1135 
1136 /** Generate texture instance
1137  *
1138  * @param gl     GL functions
1139  * @param target Texture target
1140  * @param level  Mipmap level
1141  * @param pname  Parameter to query
1142  * @param param  Result of query
1143  **/
GetLevelParameter(const glw::Functions & gl,glw::GLenum target,glw::GLint level,glw::GLenum pname,glw::GLint * param)1144 void Texture::GetLevelParameter(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLenum pname,
1145 								glw::GLint* param)
1146 {
1147 	gl.getTexLevelParameteriv(target, level, pname, param);
1148 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexLevelParameteriv");
1149 }
1150 
1151 /** Set contents of texture
1152  *
1153  * @param gl              GL functions
1154  * @param target          Texture target
1155  * @param level           Mipmap level
1156  * @param internal_format Format of data
1157  * @param width           Width of texture
1158  * @param height          Height of texture
1159  * @param depth           Depth of texture
1160  * @param format          Format of data
1161  * @param type            Type of data
1162  * @param data            Buffer with image data
1163  **/
Image(const glw::Functions & gl,glw::GLenum target,glw::GLint level,glw::GLenum internal_format,glw::GLuint width,glw::GLuint height,glw::GLuint depth,glw::GLenum format,glw::GLenum type,const glw::GLvoid * data)1164 void Texture::Image(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLenum internal_format,
1165 					glw::GLuint width, glw::GLuint height, glw::GLuint depth, glw::GLenum format, glw::GLenum type,
1166 					const glw::GLvoid* data)
1167 {
1168 	switch (target)
1169 	{
1170 	case GL_TEXTURE_1D:
1171 		gl.texImage1D(target, level, internal_format, width, 0 /* border */, format, type, data);
1172 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage1D");
1173 		break;
1174 	case GL_TEXTURE_1D_ARRAY:
1175 	case GL_TEXTURE_2D:
1176 	case GL_TEXTURE_RECTANGLE:
1177 		gl.texImage2D(target, level, internal_format, width, height, 0 /* border */, format, type, data);
1178 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage2D");
1179 		break;
1180 	case GL_TEXTURE_CUBE_MAP:
1181 		gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, internal_format, width, height, 0 /* border */, format,
1182 					  type, data);
1183 		gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, internal_format, width, height, 0 /* border */, format,
1184 					  type, data);
1185 		gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, internal_format, width, height, 0 /* border */, format,
1186 					  type, data);
1187 		gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, internal_format, width, height, 0 /* border */, format,
1188 					  type, data);
1189 		gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, internal_format, width, height, 0 /* border */, format,
1190 					  type, data);
1191 		gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, internal_format, width, height, 0 /* border */, format,
1192 					  type, data);
1193 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage2D");
1194 		break;
1195 	case GL_TEXTURE_3D:
1196 	case GL_TEXTURE_2D_ARRAY:
1197 		gl.texImage3D(target, level, internal_format, width, height, depth, 0 /* border */, format, type, data);
1198 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage3D");
1199 		break;
1200 	default:
1201 		TCU_FAIL("Invliad enum");
1202 	}
1203 }
1204 
1205 /** Allocate storage for texture
1206  *
1207  * @param gl              GL functions
1208  * @param target          Texture target
1209  * @param levels          Number of levels
1210  * @param internal_format Internal format of texture
1211  * @param width           Width of texture
1212  * @param height          Height of texture
1213  * @param depth           Depth of texture
1214  **/
Storage(const glw::Functions & gl,glw::GLenum target,glw::GLsizei levels,glw::GLenum internal_format,glw::GLuint width,glw::GLuint height,glw::GLuint depth,bool allow_error)1215 void Texture::Storage(const glw::Functions& gl, glw::GLenum target, glw::GLsizei levels, glw::GLenum internal_format,
1216 					  glw::GLuint width, glw::GLuint height, glw::GLuint depth, bool allow_error)
1217 {
1218 	switch (target)
1219 	{
1220 	case GL_TEXTURE_1D:
1221 		gl.texStorage1D(target, levels, internal_format, width);
1222 		if (!allow_error)
1223 		{
1224 			GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage1D");
1225 		}
1226 		break;
1227 	case GL_TEXTURE_1D_ARRAY:
1228 	case GL_TEXTURE_2D:
1229 	case GL_TEXTURE_RECTANGLE:
1230 	case GL_TEXTURE_CUBE_MAP:
1231 		gl.texStorage2D(target, levels, internal_format, width, height);
1232 		if (!allow_error)
1233 		{
1234 			GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
1235 		}
1236 		break;
1237 	case GL_TEXTURE_2D_MULTISAMPLE:
1238 		gl.texStorage2DMultisample(target, levels, internal_format, width, height, GL_FALSE);
1239 		if (!allow_error)
1240 		{
1241 			GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2DMultisample");
1242 		}
1243 		break;
1244 	case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1245 		gl.texStorage3DMultisample(target, levels, internal_format, width, height, depth, GL_FALSE);
1246 		if (!allow_error)
1247 		{
1248 			GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage3DMultisample");
1249 		}
1250 		break;
1251 	case GL_TEXTURE_3D:
1252 	case GL_TEXTURE_2D_ARRAY:
1253 	case GL_TEXTURE_CUBE_MAP_ARRAY:
1254 		gl.texStorage3D(target, levels, internal_format, width, height, depth);
1255 		if (!allow_error)
1256 		{
1257 			GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage3D");
1258 		}
1259 		break;
1260 	default:
1261 		TCU_FAIL("Invliad enum");
1262 	}
1263 }
1264 
1265 /** Set contents of texture
1266  *
1267  * @param gl              GL functions
1268  * @param target          Texture target
1269  * @param level           Mipmap level
1270  * @param x               X offset
1271  * @param y               Y offset
1272  * @param z               Z offset
1273  * @param width           Width of texture
1274  * @param height          Height of texture
1275  * @param depth           Depth of texture
1276  * @param format          Format of data
1277  * @param type            Type of data
1278  * @param pixels          Buffer with image data
1279  **/
SubImage(const glw::Functions & gl,glw::GLenum target,glw::GLint level,glw::GLint x,glw::GLint y,glw::GLint z,glw::GLsizei width,glw::GLsizei height,glw::GLsizei depth,glw::GLenum format,glw::GLenum type,const glw::GLvoid * pixels)1280 void Texture::SubImage(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLint x, glw::GLint y,
1281 					   glw::GLint z, glw::GLsizei width, glw::GLsizei height, glw::GLsizei depth, glw::GLenum format,
1282 					   glw::GLenum type, const glw::GLvoid* pixels)
1283 {
1284 	switch (target)
1285 	{
1286 	case GL_TEXTURE_1D:
1287 		gl.texSubImage1D(target, level, x, width, format, type, pixels);
1288 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage1D");
1289 		break;
1290 	case GL_TEXTURE_1D_ARRAY:
1291 	case GL_TEXTURE_2D:
1292 	case GL_TEXTURE_RECTANGLE:
1293 		gl.texSubImage2D(target, level, x, y, width, height, format, type, pixels);
1294 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
1295 		break;
1296 	case GL_TEXTURE_CUBE_MAP:
1297 		gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, x, y, width, height, format, type, pixels);
1298 		gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, x, y, width, height, format, type, pixels);
1299 		gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, x, y, width, height, format, type, pixels);
1300 		gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, x, y, width, height, format, type, pixels);
1301 		gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, x, y, width, height, format, type, pixels);
1302 		gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, x, y, width, height, format, type, pixels);
1303 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
1304 		break;
1305 	case GL_TEXTURE_3D:
1306 	case GL_TEXTURE_2D_ARRAY:
1307 	case GL_TEXTURE_CUBE_MAP_ARRAY:
1308 		gl.texSubImage3D(target, level, x, y, z, width, height, depth, format, type, pixels);
1309 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage3D");
1310 		break;
1311 	default:
1312 		TCU_FAIL("Invliad enum");
1313 	}
1314 }
1315 
1316 /* Gather info about buffer target */
1317 struct bufferTargetInfo
1318 {
1319 	GLenum m_target;
1320 	GLenum m_pname_alignment;
1321 	GLenum m_pname_binding;
1322 	GLenum m_pname_max;
1323 	GLenum m_pname_max_size;
1324 };
1325 
1326 /* Gather info about texture target */
1327 struct textureTargetInfo
1328 {
1329 	GLenum		  m_target;
1330 	GLenum		  m_pname_binding;
1331 	const GLchar* m_name;
1332 };
1333 
1334 /* Collects information about buffers */
1335 static const bufferTargetInfo s_buffer_infos[] = {
1336 	{ GL_ATOMIC_COUNTER_BUFFER, 0, GL_ATOMIC_COUNTER_BUFFER_BINDING, GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS,
1337 	  GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE },
1338 	{
1339 		GL_TRANSFORM_FEEDBACK_BUFFER, 0, GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, GL_MAX_TRANSFORM_FEEDBACK_BUFFERS,
1340 		GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,
1341 	},
1342 	{ GL_UNIFORM_BUFFER, GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, GL_UNIFORM_BUFFER_BINDING, GL_MAX_UNIFORM_BUFFER_BINDINGS,
1343 	  GL_MAX_UNIFORM_BLOCK_SIZE },
1344 	{ GL_SHADER_STORAGE_BUFFER, GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, GL_SHADER_STORAGE_BUFFER_BINDING,
1345 	  GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, GL_MAX_SHADER_STORAGE_BLOCK_SIZE },
1346 };
1347 
1348 static const size_t s_n_buffer_tragets = sizeof(s_buffer_infos) / sizeof(s_buffer_infos[0]);
1349 
1350 /* Collects information about textures */
1351 static const textureTargetInfo s_texture_infos[] = {
1352 	{ GL_TEXTURE_1D, GL_TEXTURE_BINDING_1D, "1D" },
1353 	{ GL_TEXTURE_1D_ARRAY, GL_TEXTURE_BINDING_1D_ARRAY, "1D_ARRAY" },
1354 	{ GL_TEXTURE_2D, GL_TEXTURE_BINDING_2D, "2D" },
1355 	{ GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BINDING_2D_ARRAY, "2D_ARRAY" },
1356 	{ GL_TEXTURE_3D, GL_TEXTURE_BINDING_3D, "3D" },
1357 	{ GL_TEXTURE_BUFFER, GL_TEXTURE_BINDING_BUFFER, "BUFFER" },
1358 	{ GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BINDING_CUBE_MAP, "CUBE" },
1359 	{ GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_BINDING_CUBE_MAP_ARRAY, "CUBE_ARRAY" },
1360 	{ GL_TEXTURE_RECTANGLE, GL_TEXTURE_BINDING_RECTANGLE, "RECTANGLE" },
1361 	{ GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_BINDING_2D_MULTISAMPLE, "2D_MS" },
1362 	{ GL_TEXTURE_2D_MULTISAMPLE_ARRAY, GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY, "2D_MS_ARRAY" }
1363 };
1364 
1365 static const size_t s_n_texture_tragets = sizeof(s_texture_infos) / sizeof(s_texture_infos[0]);
1366 
1367 /** Macro, verifies generated error, logs error message and throws failure
1368  *
1369  * @param expected_error Expected error value
1370  * @param error_message  Message logged if generated error is not the expected one
1371  **/
1372 #define CHECK_ERROR(expected_error, error_message)                                                      \
1373 	do {                                                                                                   \
1374 		GLenum generated_error = gl.getError();                                                         \
1375                                                                                                         \
1376 		if (expected_error != generated_error)                                                          \
1377 		{                                                                                               \
1378 			m_context.getTestContext().getLog()                                                         \
1379 				<< tcu::TestLog::Message << "File: " << __FILE__ << ", line: " << __LINE__              \
1380 				<< ". Got wrong error: " << glu::getErrorStr(generated_error)                           \
1381 				<< ", expected: " << glu::getErrorStr(expected_error) << ", message: " << error_message \
1382 				<< tcu::TestLog::EndMessage;                                                            \
1383 			TCU_FAIL("Invalid error generated");                                                        \
1384 		}                                                                                               \
1385 	} while (0)
1386 
1387 /* Prototypes */
1388 void replaceToken(const GLchar* token, size_t& search_position, const GLchar* text, std::string& string);
1389 
1390 /** Checks binding
1391  *
1392  * @param context        Test contex
1393  * @param pname          Pname of binding
1394  * @param index          Index of binding
1395  * @param target_name    Name of target
1396  * @param expected_value Expected value of binding
1397  **/
checkBinding(deqp::Context & context,GLenum pname,GLuint index,const std::string & target_name,GLint expected_value)1398 void checkBinding(deqp::Context& context, GLenum pname, GLuint index, const std::string& target_name,
1399 				  GLint expected_value)
1400 {
1401 	const Functions& gl = context.getRenderContext().getFunctions();
1402 
1403 	GLint binding = -1;
1404 
1405 	gl.getIntegeri_v(pname, index, &binding);
1406 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegeri_v");
1407 
1408 	if (binding != expected_value)
1409 	{
1410 		context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid binding: " << binding
1411 										  << ", expected: " << expected_value << ". Target: " << target_name
1412 										  << " at index: " << index << tcu::TestLog::EndMessage;
1413 		TCU_FAIL("Invalid binding");
1414 	}
1415 }
1416 
1417 /** Checks bindings for given texture unit
1418  *
1419  * @param context        Test contex
1420  * @param pname          Binding pname of <expected_value>
1421  * @param index          Index of texture unit
1422  * @param expected_value Expected value of binding at <pname> target
1423  **/
checkTextureBinding(deqp::Context & context,GLenum pname,GLuint index,GLint expected_value)1424 void checkTextureBinding(deqp::Context& context, GLenum pname, GLuint index, GLint expected_value)
1425 {
1426 	const Functions& gl = context.getRenderContext().getFunctions();
1427 
1428 	for (size_t i = 0; i < s_n_texture_tragets; ++i)
1429 	{
1430 		const GLenum  pname_binding = s_texture_infos[i].m_pname_binding;
1431 		const GLchar* target_name   = s_texture_infos[i].m_name;
1432 
1433 		GLint binding = -1;
1434 		GLint value   = 0;
1435 
1436 		gl.getIntegeri_v(pname_binding, index, &binding);
1437 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegeri_v");
1438 
1439 		if (pname_binding == pname)
1440 		{
1441 			value = (GLint)expected_value;
1442 		}
1443 
1444 		if (binding != value)
1445 		{
1446 			context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid binding: " << binding
1447 											  << ", expected: " << expected_value << ". Target: " << target_name
1448 											  << " at index: " << index << tcu::TestLog::EndMessage;
1449 			TCU_FAIL("Invalid binding");
1450 		}
1451 	}
1452 }
1453 
1454 /** Checks binding
1455  *
1456  * @param context        Test context
1457  * @param index          Index of binding
1458  * @param expected_value Expected value of binding
1459  **/
checkVertexAttribBinding(deqp::Context & context,GLuint index,GLint expected_value)1460 void checkVertexAttribBinding(deqp::Context& context, GLuint index, GLint expected_value)
1461 {
1462 	const Functions& gl = context.getRenderContext().getFunctions();
1463 
1464 	GLint binding = -1;
1465 
1466 	gl.getVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &binding);
1467 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetVertexAttribiv");
1468 
1469 	if (binding != expected_value)
1470 	{
1471 		context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid binding: " << binding
1472 										  << ", expected: " << expected_value << ". Target: Vertex attribute"
1473 										  << " at index: " << index << tcu::TestLog::EndMessage;
1474 		TCU_FAIL("Invalid binding");
1475 	}
1476 }
1477 
1478 /** Fills MS texture with specified value
1479  *
1480  * @param context        Test context
1481  * @param texture_id     Index of binding
1482  * @param value          Value for texture
1483  * @param is_array       Selects if array target should be used
1484  **/
fillMSTexture(deqp::Context & context,GLuint texture_id,GLuint value,bool is_array)1485 void fillMSTexture(deqp::Context& context, GLuint texture_id, GLuint value, bool is_array)
1486 {
1487 	/* */
1488 	static const GLchar* cs = "#version 430 core\n"
1489 							  "\n"
1490 							  "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1491 							  "\n"
1492 							  "layout (location = 0) writeonly uniform IMAGE uni_image;\n"
1493 							  "\n"
1494 							  "layout (location = 1) uniform uint uni_value;\n"
1495 							  "\n"
1496 							  "void main()\n"
1497 							  "{\n"
1498 							  "    const POINT;\n"
1499 							  "\n"
1500 							  "    imageStore(uni_image, point, 0, uvec4(uni_value, 0, 0, 0));\n"
1501 							  "}\n"
1502 							  "\n";
1503 
1504 	static const GLchar* array_image   = "uimage2DMSArray";
1505 	static const GLchar* array_point   = "ivec3 point = ivec3(gl_WorkGroupID.x, gl_WorkGroupID.y, 0)";
1506 	static const GLchar* regular_image = "uimage2DMS";
1507 	static const GLchar* regular_point = "ivec2 point = ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y)";
1508 
1509 	/* */
1510 	const Functions& gl		  = context.getRenderContext().getFunctions();
1511 	const GLchar*	image	= (true == is_array) ? array_image : regular_image;
1512 	const GLchar*	point	= (true == is_array) ? array_point : regular_point;
1513 	size_t			 position = 0;
1514 	std::string		 source   = cs;
1515 
1516 	/* */
1517 	replaceToken("IMAGE", position, image, source);
1518 	replaceToken("POINT", position, point, source);
1519 
1520 	/* */
1521 	Program program(context);
1522 	program.Init(source.c_str(), "", "", "", "", "");
1523 	program.Use();
1524 
1525 	/* */
1526 	if (true == is_array)
1527 	{
1528 		gl.bindImageTexture(0 /* unit */, texture_id, 0 /* level */, GL_TRUE /* layered */, 0 /* layer */,
1529 							GL_WRITE_ONLY, GL_R32UI);
1530 	}
1531 	else
1532 	{
1533 		gl.bindImageTexture(0 /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
1534 							GL_WRITE_ONLY, GL_R32UI);
1535 	}
1536 
1537 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
1538 
1539 	gl.uniform1i(0 /* location */, 0 /* image unit*/);
1540 	GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
1541 
1542 	gl.uniform1ui(1 /* location */, value /* uni_value */);
1543 	GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1ui");
1544 
1545 	/* */
1546 	gl.dispatchCompute(6, 6, 1);
1547 	GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
1548 }
1549 
1550 /** Get texture binding pname for given index
1551  *
1552  * @param index Index of texture target
1553  *
1554  * @return Pname
1555  **/
getBinding(GLuint index)1556 GLenum getBinding(GLuint index)
1557 {
1558 	if (index < s_n_texture_tragets)
1559 	{
1560 		return s_texture_infos[index].m_pname_binding;
1561 	}
1562 	else
1563 	{
1564 		return GL_TEXTURE_BINDING_2D;
1565 	}
1566 }
1567 
1568 /** Get texture target for given index
1569  *
1570  * @param index Index of texture target
1571  *
1572  * @return Target
1573  **/
getTarget(GLuint index)1574 GLenum getTarget(GLuint index)
1575 {
1576 	if (index < s_n_texture_tragets)
1577 	{
1578 		return s_texture_infos[index].m_target;
1579 	}
1580 	else
1581 	{
1582 		return GL_TEXTURE_2D;
1583 	}
1584 }
1585 
1586 /** Replace first occurance of <token> with <text> in <string> starting at <search_posistion>
1587  *
1588  * @param token           Token string
1589  * @param search_position Position at which find will start, it is updated to position at which replaced text ends
1590  * @param text            String that will be used as replacement for <token>
1591  * @param string          String to work on
1592  **/
replaceToken(const GLchar * token,size_t & search_position,const GLchar * text,std::string & string)1593 void replaceToken(const GLchar* token, size_t& search_position, const GLchar* text, std::string& string)
1594 {
1595 	const size_t text_length	= strlen(text);
1596 	const size_t token_length   = strlen(token);
1597 	const size_t token_position = string.find(token, search_position);
1598 
1599 	string.replace(token_position, token_length, text, text_length);
1600 
1601 	search_position = token_position + text_length;
1602 }
1603 
1604 /** Constructor
1605  *
1606  * @param context Test context
1607  **/
ErrorsBindBuffersTest(deqp::Context & context)1608 ErrorsBindBuffersTest::ErrorsBindBuffersTest(deqp::Context& context)
1609 	: TestCase(context, "errors_bind_buffers", "Verifies that proper errors are generated by buffer binding routines")
1610 {
1611 	/* Nothing to be done */
1612 }
1613 
1614 /** Execute test
1615  *
1616  * @return tcu::TestNode::STOP
1617  **/
iterate()1618 tcu::TestNode::IterateResult ErrorsBindBuffersTest::iterate()
1619 {
1620 	const Functions& gl = m_context.getRenderContext().getFunctions();
1621 
1622 #if DEBUG_ENBALE_MESSAGE_CALLBACK
1623 	gl.debugMessageCallback(debug_proc, &m_context);
1624 	GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
1625 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
1626 
1627 	/* - INVALID_ENUM when <target> is not valid; */
1628 	{
1629 		static const GLintptr buffer_size = 16;
1630 		static const GLsizei  count		  = 1;
1631 		static const GLuint   first		  = 0;
1632 		static const GLintptr offset	  = 4;
1633 		static const GLintptr size		  = buffer_size - offset;
1634 
1635 		Buffer buffer;
1636 
1637 		buffer.InitData(m_context, GL_ARRAY_BUFFER, GL_DYNAMIC_COPY, buffer_size, 0 /* data */);
1638 
1639 		gl.bindBuffersBase(GL_ARRAY_BUFFER, first, count, &buffer.m_id);
1640 		CHECK_ERROR(GL_INVALID_ENUM, "BindBuffersBase with invalid <target>");
1641 
1642 		gl.bindBuffersRange(GL_ARRAY_BUFFER, first, count, &buffer.m_id, &offset, &size);
1643 		CHECK_ERROR(GL_INVALID_ENUM, "BindBuffersRange with invalid <target>");
1644 	}
1645 
1646 	for (size_t i = 0; i < s_n_buffer_tragets; ++i)
1647 	{
1648 		static const GLsizei n_buffers = 4;
1649 
1650 		const GLenum	   pname_alignment = s_buffer_infos[i].m_pname_alignment;
1651 		const GLenum	   pname_max	   = s_buffer_infos[i].m_pname_max;
1652 		const GLenum	   target		   = s_buffer_infos[i].m_target;
1653 		const std::string& target_name	 = glu::getBufferTargetStr(target).toString();
1654 
1655 		GLintptr buffer_size	  = 16;
1656 		GLsizei  count			  = n_buffers;
1657 		GLuint   first			  = 0;
1658 		GLuint   invalid_id		  = 1; /* Start with 1, as 0 is not valid name */
1659 		GLintptr offset			  = 4; /* ATOMIC and XFB require alignment of 4 */
1660 		GLint	offset_alignment = 1;
1661 		GLint	max_buffers	  = 0;
1662 		GLintptr size			  = buffer_size - offset;
1663 		size_t   validated_index  = n_buffers - 1;
1664 
1665 		/* Get alignment */
1666 		if (0 != pname_alignment)
1667 		{
1668 			gl.getIntegerv(pname_alignment, &offset_alignment);
1669 			GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1670 
1671 			buffer_size += offset_alignment;
1672 			offset = offset_alignment;
1673 			size   = buffer_size - offset;
1674 		}
1675 
1676 		/* Get max */
1677 		gl.getIntegerv(pname_max, &max_buffers);
1678 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1679 
1680 		/* Select count so <first + count> does not exceed max.
1681 		 * Validated index shall be in the specified range.
1682 		 */
1683 		if (n_buffers > max_buffers)
1684 		{
1685 			count			= max_buffers;
1686 			validated_index = max_buffers - 1;
1687 		}
1688 
1689 		/* Storage */
1690 		Buffer   buffer[n_buffers];
1691 		GLuint   buffer_ids[n_buffers];
1692 		GLintptr offsets[n_buffers];
1693 		GLintptr sizes[n_buffers];
1694 
1695 		/* Prepare buffers */
1696 		for (size_t j = 0; j < n_buffers; ++j)
1697 		{
1698 			buffer[j].InitData(m_context, target, GL_DYNAMIC_COPY, buffer_size, 0 /* data */);
1699 
1700 			buffer_ids[j] = buffer[j].m_id;
1701 			offsets[j]	= offset;
1702 			sizes[j]	  = size;
1703 		}
1704 
1705 		/* - INVALID_OPERATION when <first> + <count> is greater than allowed limit; */
1706 		{
1707 			GLsizei t_count = n_buffers;
1708 			GLuint  t_first = 0;
1709 
1710 			/* Select first so <first + count> exceeds max, avoid negative first */
1711 			if (n_buffers <= max_buffers)
1712 			{
1713 				t_first = max_buffers - n_buffers + 1;
1714 			}
1715 			else
1716 			{
1717 				t_count = max_buffers + 1;
1718 				/* first = 0; */
1719 			}
1720 
1721 			/* Test */
1722 			gl.bindBuffersBase(target, t_first, t_count, buffer_ids);
1723 			CHECK_ERROR(GL_INVALID_OPERATION,
1724 						"BindBuffersBase with invalid <first> + <count>, target: " << target_name);
1725 
1726 			gl.bindBuffersRange(target, t_first, t_count, buffer_ids, offsets, sizes);
1727 			CHECK_ERROR(GL_INVALID_OPERATION,
1728 						"BindBuffersRange with invalid <first> + <count>, target: " << target_name);
1729 		}
1730 
1731 		/* - INVALID_OPERATION if any value in <buffers> is not zero or the name of
1732 		 * existing buffer;
1733 		 */
1734 		{
1735 			GLuint t_buffer_ids[n_buffers];
1736 
1737 			memcpy(t_buffer_ids, buffer_ids, sizeof(buffer_ids));
1738 
1739 			/* Find invalid id */
1740 			while (1)
1741 			{
1742 				if (GL_TRUE != gl.isBuffer(invalid_id))
1743 				{
1744 					break;
1745 				}
1746 
1747 				invalid_id += 1;
1748 			}
1749 
1750 			/* Invalidate the entry */
1751 			t_buffer_ids[validated_index] = invalid_id;
1752 
1753 			/* Test */
1754 			gl.bindBuffersBase(target, first, count, t_buffer_ids);
1755 			CHECK_ERROR(GL_INVALID_OPERATION, "BindBuffersBase with invalid buffer id, target: " << target_name);
1756 
1757 			gl.bindBuffersRange(target, first, count, t_buffer_ids, offsets, sizes);
1758 			CHECK_ERROR(GL_INVALID_OPERATION, "BindBuffersRange with invalid buffer id, target: " << target_name);
1759 		}
1760 
1761 		/* - INVALID_VALUE if any value in <offsets> is less than zero; */
1762 		{
1763 			GLintptr t_offsets[n_buffers];
1764 			GLintptr t_sizes[n_buffers];
1765 
1766 			memcpy(t_offsets, offsets, sizeof(offsets));
1767 			memcpy(t_sizes, sizes, sizeof(sizes));
1768 
1769 			/* Invalidate the entry */
1770 			t_offsets[validated_index] = -1;
1771 			t_sizes[validated_index]   = -1;
1772 
1773 			/* Test */
1774 			gl.bindBuffersRange(target, first, count, buffer_ids, t_offsets, sizes);
1775 			CHECK_ERROR(GL_INVALID_VALUE, "BindBuffersRange with negative offset, target: " << target_name);
1776 
1777 			/* Test */
1778 			gl.bindBuffersRange(target, first, count, buffer_ids, offsets, t_sizes);
1779 			CHECK_ERROR(GL_INVALID_VALUE, "BindBuffersRange with negative size, target: " << target_name);
1780 		}
1781 
1782 		/* - INVALID_VALUE if any pair of <offsets> and <sizes> exceeds limits. */
1783 		{
1784 			GLintptr t_offsets[n_buffers];
1785 			GLintptr t_sizes[n_buffers];
1786 
1787 			memcpy(t_offsets, offsets, sizeof(offsets));
1788 			memcpy(t_sizes, sizes, sizeof(sizes));
1789 
1790 			/* Invalidate the entry */
1791 			t_offsets[validated_index] -= 1;	 /* Not aligned by required value */
1792 			t_sizes[validated_index] = size - 1; /* Not aligned by required value */
1793 
1794 			/* Test */
1795 			gl.bindBuffersRange(target, first, count, buffer_ids, t_offsets, sizes);
1796 			CHECK_ERROR(GL_INVALID_VALUE, "BindBuffersRange with invalid <offset>, target: " << target_name);
1797 
1798 			/* Test */
1799 			if (GL_TRANSFORM_FEEDBACK_BUFFER == target)
1800 			{
1801 				gl.bindBuffersRange(target, first, count, buffer_ids, offsets, t_sizes);
1802 				CHECK_ERROR(GL_INVALID_VALUE, "BindBuffersRange with invalid <size>, target: " << target_name);
1803 			}
1804 		}
1805 	}
1806 
1807 	/* Set result */
1808 	m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1809 
1810 	/* Done */
1811 	return tcu::TestNode::STOP;
1812 }
1813 
1814 /** Constructor
1815  *
1816  * @param context Test context
1817  **/
ErrorsBindTexturesTest(deqp::Context & context)1818 ErrorsBindTexturesTest::ErrorsBindTexturesTest(deqp::Context& context)
1819 	: TestCase(context, "errors_bind_textures", "Verifies that proper errors are generated by texture binding routines")
1820 {
1821 	/* Nothing to be done */
1822 }
1823 
1824 /** Execute test
1825  *
1826  * @return tcu::TestNode::STOP
1827  **/
iterate()1828 tcu::TestNode::IterateResult ErrorsBindTexturesTest::iterate()
1829 {
1830 	static const GLuint  depth		= 8;
1831 	static const GLuint  height		= 8;
1832 	static const GLsizei n_textures = 4;
1833 	static const GLuint  width		= 8;
1834 
1835 	const Functions& gl = m_context.getRenderContext().getFunctions();
1836 
1837 #if DEBUG_ENBALE_MESSAGE_CALLBACK
1838 	gl.debugMessageCallback(debug_proc, &m_context);
1839 	GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
1840 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
1841 
1842 	GLsizei count			= n_textures;
1843 	GLuint  first			= 0;
1844 	GLuint  invalid_id		= 1; /* Start with 1, as 0 is not valid name */
1845 	GLint   max_textures	= 0;
1846 	size_t  validated_index = n_textures - 1;
1847 
1848 	/* Get max */
1849 	gl.getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_textures);
1850 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1851 
1852 	/* Select count so <first + count> does not exceed max.
1853 	 * Validated index shall be in the specified range.
1854 	 */
1855 	if (n_textures > max_textures)
1856 	{
1857 		count			= max_textures;
1858 		validated_index = max_textures - 1;
1859 	}
1860 
1861 	/* Storage */
1862 	Texture texture[n_textures];
1863 	GLuint  texture_ids[n_textures];
1864 
1865 	/* Prepare textures */
1866 	texture[0].InitStorage(m_context, GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, width, height, depth);
1867 	texture[1].InitStorage(m_context, GL_TEXTURE_2D_ARRAY, 1 /* levels */, GL_RGBA8, width, height, depth);
1868 	texture[2].InitStorage(m_context, GL_TEXTURE_1D_ARRAY, 1 /* levels */, GL_RGBA8, width, height, depth);
1869 	texture[3].InitStorage(m_context, GL_TEXTURE_3D, 1 /* levels */, GL_RGBA8, width, height, depth);
1870 
1871 	for (size_t i = 0; i < n_textures; ++i)
1872 	{
1873 		texture_ids[i] = texture[i].m_id;
1874 	}
1875 
1876 	/* - INVALID_OPERATION when <first> + <count> exceed limits; */
1877 	{
1878 		GLsizei t_count = n_textures;
1879 		GLuint  t_first = 0;
1880 
1881 		/* Select first so <first + count> exceeds max, avoid negative first */
1882 		if (n_textures <= max_textures)
1883 		{
1884 			t_first = max_textures - n_textures + 1;
1885 		}
1886 		else
1887 		{
1888 			t_count = max_textures + 1;
1889 			/* first = 0; */
1890 		}
1891 
1892 		/* Test */
1893 		gl.bindTextures(t_first, t_count, texture_ids);
1894 		CHECK_ERROR(GL_INVALID_OPERATION, "BindTextures with invalid <first> + <count>");
1895 	}
1896 
1897 	/* - INVALID_OPERATION if any value in <buffers> is not zero or the name of
1898 	 * existing buffer;
1899 	 */
1900 	{
1901 		GLuint t_texture_ids[n_textures];
1902 
1903 		memcpy(t_texture_ids, texture_ids, sizeof(texture_ids));
1904 
1905 		/* Find invalid id */
1906 		while (1)
1907 		{
1908 			if (GL_TRUE != gl.isTexture(invalid_id))
1909 			{
1910 				break;
1911 			}
1912 
1913 			invalid_id += 1;
1914 		}
1915 
1916 		/* Invalidate the entry */
1917 		t_texture_ids[validated_index] = invalid_id;
1918 
1919 		/* Test */
1920 		gl.bindTextures(first, count, t_texture_ids);
1921 		CHECK_ERROR(GL_INVALID_OPERATION, "BindTextures with invalid texture id");
1922 	}
1923 
1924 	/* Set result */
1925 	m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1926 
1927 	/* Done */
1928 	return tcu::TestNode::STOP;
1929 }
1930 
1931 /** Constructor
1932  *
1933  * @param context Test context
1934  **/
ErrorsBindSamplersTest(deqp::Context & context)1935 ErrorsBindSamplersTest::ErrorsBindSamplersTest(deqp::Context& context)
1936 	: TestCase(context, "errors_bind_samplers", "Verifies that proper errors are generated by sampler binding routines")
1937 {
1938 	/* Nothing to be done */
1939 }
1940 
1941 /** Execute test
1942  *
1943  * @return tcu::TestNode::STOP
1944  **/
iterate()1945 tcu::TestNode::IterateResult ErrorsBindSamplersTest::iterate()
1946 {
1947 	static const GLsizei n_samplers = 4;
1948 
1949 	const Functions& gl = m_context.getRenderContext().getFunctions();
1950 
1951 #if DEBUG_ENBALE_MESSAGE_CALLBACK
1952 	gl.debugMessageCallback(debug_proc, &m_context);
1953 	GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
1954 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
1955 
1956 	GLsizei count			= n_samplers;
1957 	GLuint  first			= 0;
1958 	GLuint  invalid_id		= 1; /* Start with 1, as 0 is not valid name */
1959 	GLint   max_samplers	= 0;
1960 	size_t  validated_index = n_samplers - 1;
1961 
1962 	/* Get max */
1963 	gl.getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_samplers);
1964 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1965 
1966 	/* Select count so <first + count> does not exceed max.
1967 	 * Validated index shall be in the specified range.
1968 	 */
1969 	if (n_samplers > max_samplers)
1970 	{
1971 		count			= max_samplers;
1972 		validated_index = max_samplers - 1;
1973 	}
1974 
1975 	/* Storage */
1976 	GLuint sampler_ids[n_samplers];
1977 
1978 	/* Prepare samplers */
1979 	gl.genSamplers(n_samplers, sampler_ids);
1980 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenSamplers");
1981 
1982 	try
1983 	{
1984 		/* - INVALID_OPERATION when <first> + <count> exceed limits; */
1985 		{
1986 			GLsizei t_count = n_samplers;
1987 			GLuint  t_first = 0;
1988 
1989 			/* Select first so <first + count> exceeds max, avoid negative first */
1990 			if (n_samplers <= max_samplers)
1991 			{
1992 				t_first = max_samplers - n_samplers + 1;
1993 			}
1994 			else
1995 			{
1996 				t_count = max_samplers + 1;
1997 				/* first = 0; */
1998 			}
1999 
2000 			/* Test */
2001 			gl.bindSamplers(t_first, t_count, sampler_ids);
2002 			CHECK_ERROR(GL_INVALID_OPERATION, "BindSamplers with invalid <first> + <count>");
2003 		}
2004 
2005 		/* - INVALID_OPERATION if any value in <buffers> is not zero or the name of
2006 		 * existing buffer;
2007 		 */
2008 		{
2009 			GLuint t_sampler_ids[n_samplers];
2010 
2011 			memcpy(t_sampler_ids, sampler_ids, sizeof(sampler_ids));
2012 
2013 			/* Find invalid id */
2014 			while (1)
2015 			{
2016 				if (GL_TRUE != gl.isTexture(invalid_id))
2017 				{
2018 					break;
2019 				}
2020 
2021 				invalid_id += 1;
2022 			}
2023 
2024 			/* Invalidate the entry */
2025 			t_sampler_ids[validated_index] = invalid_id;
2026 
2027 			/* Test */
2028 			gl.bindTextures(first, count, t_sampler_ids);
2029 			CHECK_ERROR(GL_INVALID_OPERATION, "BindSamplers with invalid sampler id");
2030 		}
2031 	}
2032 	catch (const std::exception&)
2033 	{
2034 		gl.deleteSamplers(n_samplers, sampler_ids);
2035 
2036 		TCU_FAIL("Invalid error generated");
2037 	}
2038 
2039 	/* Delete samplers */
2040 	gl.deleteSamplers(n_samplers, sampler_ids);
2041 
2042 	/* Set result */
2043 	m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2044 
2045 	/* Done */
2046 	return tcu::TestNode::STOP;
2047 }
2048 
2049 /** Constructor
2050  *
2051  * @param context Test context
2052  **/
ErrorsBindImageTexturesTest(deqp::Context & context)2053 ErrorsBindImageTexturesTest::ErrorsBindImageTexturesTest(deqp::Context& context)
2054 	: TestCase(context, "errors_bind_image_textures",
2055 			   "Verifies that proper errors are generated by image binding routines")
2056 {
2057 	/* Nothing to be done */
2058 }
2059 
2060 /** Execute test
2061  *
2062  * @return tcu::TestNode::STOP
2063  **/
iterate()2064 tcu::TestNode::IterateResult ErrorsBindImageTexturesTest::iterate()
2065 {
2066 	static const GLuint  depth		= 8;
2067 	static const GLuint  height		= 8;
2068 	static const GLsizei n_textures = 4;
2069 	static const GLuint  width		= 8;
2070 
2071 	const Functions& gl = m_context.getRenderContext().getFunctions();
2072 
2073 #if DEBUG_ENBALE_MESSAGE_CALLBACK
2074 	gl.debugMessageCallback(debug_proc, &m_context);
2075 	GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
2076 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
2077 
2078 	GLsizei count			= n_textures;
2079 	GLuint  first			= 0;
2080 	GLuint  invalid_id		= 1; /* Start with 1, as 0 is not valid name */
2081 	GLint   max_textures	= 0;
2082 	size_t  validated_index = n_textures - 1;
2083 
2084 	/* Get max */
2085 	gl.getIntegerv(GL_MAX_IMAGE_UNITS, &max_textures);
2086 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2087 
2088 	/* Select count so <first + count> does not exceed max.
2089 	 * Validated index shall be in the specified range.
2090 	 */
2091 	if (n_textures > max_textures)
2092 	{
2093 		count			= max_textures;
2094 		validated_index = max_textures - 1;
2095 	}
2096 
2097 	/* Storage */
2098 	Texture texture[n_textures];
2099 	GLuint  texture_ids[n_textures];
2100 
2101 	/* Prepare textures */
2102 	texture[0].InitStorage(m_context, GL_TEXTURE_2D, 1, GL_RGBA8, width, height, depth);
2103 	texture[1].InitStorage(m_context, GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, width, height, depth);
2104 	texture[2].InitStorage(m_context, GL_TEXTURE_1D_ARRAY, 1, GL_RGBA8, width, height, depth);
2105 	texture[3].InitStorage(m_context, GL_TEXTURE_3D, 1, GL_RGBA8, width, height, depth);
2106 
2107 	for (size_t i = 0; i < n_textures; ++i)
2108 	{
2109 		texture_ids[i] = texture[i].m_id;
2110 	}
2111 
2112 	/* - INVALID_OPERATION when <first> + <count> exceed limits; */
2113 	{
2114 		GLsizei t_count = n_textures;
2115 		GLuint  t_first = 0;
2116 
2117 		/* Select first so <first + count> exceeds max, avoid negative first */
2118 		if (n_textures <= max_textures)
2119 		{
2120 			t_first = max_textures - n_textures + 1;
2121 		}
2122 		else
2123 		{
2124 			t_count = max_textures + 1;
2125 			/* first = 0; */
2126 		}
2127 
2128 		/* Test */
2129 		gl.bindImageTextures(t_first, t_count, texture_ids);
2130 		CHECK_ERROR(GL_INVALID_OPERATION, "BindImageTextures with invalid <first> + <count>");
2131 	}
2132 
2133 	/* - INVALID_OPERATION if any value in <buffers> is not zero or the name of
2134 	 * existing buffer;
2135 	 */
2136 	{
2137 		GLuint t_texture_ids[n_textures];
2138 
2139 		memcpy(t_texture_ids, texture_ids, sizeof(texture_ids));
2140 
2141 		/* Find invalid id */
2142 		while (1)
2143 		{
2144 			if (GL_TRUE != gl.isTexture(invalid_id))
2145 			{
2146 				break;
2147 			}
2148 
2149 			invalid_id += 1;
2150 		}
2151 
2152 		/* Invalidate the entry */
2153 		t_texture_ids[validated_index] = invalid_id;
2154 
2155 		/* Test */
2156 		gl.bindImageTextures(first, count, t_texture_ids);
2157 		CHECK_ERROR(GL_INVALID_OPERATION, "BindImageTextures with invalid texture id");
2158 	}
2159 
2160 	/* - INVALID_OPERATION if any entry found in <textures> has invalid internal
2161 	 * format at level 0;
2162 	 */
2163 	{
2164 		GLuint t_texture_ids[n_textures];
2165 
2166 		memcpy(t_texture_ids, texture_ids, sizeof(texture_ids));
2167 
2168 		/* Prepare texture with invalid format */
2169 		Texture t_texture;
2170 		t_texture.Init(m_context);
2171 		t_texture.Generate(gl, t_texture.m_id);
2172 		t_texture.Bind(gl, t_texture.m_id, GL_TEXTURE_2D);
2173 		gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGB9_E5, width, 0);
2174 		CHECK_ERROR(GL_INVALID_VALUE, "texStorage2D has height set to 0");
2175 
2176 		/* Invalidate the entry */
2177 		t_texture_ids[validated_index] = t_texture.m_id;
2178 
2179 		/* Test */
2180 		gl.bindImageTextures(first, count, t_texture_ids);
2181 		CHECK_ERROR(GL_INVALID_OPERATION, "BindImageTextures with invalid internal format");
2182 	}
2183 
2184 	/* - INVALID_VALUE when any entry in <textures> has any of dimensions equal
2185 	 * to 0 at level 0.
2186 	 */
2187 	{
2188 		GLuint t_texture_ids[n_textures];
2189 
2190 		memcpy(t_texture_ids, texture_ids, sizeof(texture_ids));
2191 
2192 		/* Prepare texture with invalid format */
2193 		Texture t_texture;
2194 		t_texture.InitStorage(m_context, GL_TEXTURE_2D, 1, GL_RGB9_E5, width, 0, depth, true);
2195 
2196 		/* Invalidate the entry */
2197 		t_texture_ids[validated_index] = t_texture.m_id;
2198 
2199 		/* Test */
2200 		gl.bindImageTextures(first, count, t_texture_ids);
2201 		CHECK_ERROR(GL_INVALID_VALUE, "BindImageTextures with 2D texture that has height set to 0");
2202 	}
2203 
2204 	/* Set result */
2205 	m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2206 
2207 	/* Done */
2208 	return tcu::TestNode::STOP;
2209 }
2210 
2211 /** Constructor
2212  *
2213  * @param context Test context
2214  **/
ErrorsBindVertexBuffersTest(deqp::Context & context)2215 ErrorsBindVertexBuffersTest::ErrorsBindVertexBuffersTest(deqp::Context& context)
2216 	: TestCase(context, "errors_bind_vertex_buffers",
2217 			   "Verifies that proper errors are generated by vertex buffer binding routines")
2218 {
2219 	/* Nothing to be done */
2220 }
2221 
2222 /** Execute test
2223  *
2224  * @return tcu::TestNode::STOP
2225  **/
iterate()2226 tcu::TestNode::IterateResult ErrorsBindVertexBuffersTest::iterate()
2227 {
2228 	const Functions& gl = m_context.getRenderContext().getFunctions();
2229 
2230 #if DEBUG_ENBALE_MESSAGE_CALLBACK
2231 	gl.debugMessageCallback(debug_proc, &m_context);
2232 	GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
2233 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
2234 
2235 	static const GLsizei n_buffers = 4;
2236 	static const GLsizei stride	= 4;
2237 
2238 	GLintptr buffer_size	 = 16;
2239 	GLsizei  count			 = n_buffers;
2240 	GLuint   first			 = 0;
2241 	GLuint   invalid_id		 = 1; /* Start with 1, as 0 is not valid name */
2242 	GLintptr offset			 = 4; /* ATOMIC and XFB require alignment of 4 */
2243 	GLint	max_buffers	 = 0;
2244 	size_t   validated_index = n_buffers - 1;
2245 
2246 	/* Get max */
2247 	gl.getIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &max_buffers);
2248 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2249 
2250 	/* Select count so <first + count> does not exceed max.
2251 	 * Validated index shall be in the specified range.
2252 	 */
2253 	if (n_buffers > max_buffers)
2254 	{
2255 		count			= max_buffers;
2256 		validated_index = max_buffers - 1;
2257 	}
2258 
2259 	/* Storage */
2260 	Buffer   buffer[n_buffers];
2261 	GLuint   buffer_ids[n_buffers];
2262 	GLintptr offsets[n_buffers];
2263 	GLsizei  strides[n_buffers];
2264 
2265 	/* Prepare buffers */
2266 	for (size_t j = 0; j < n_buffers; ++j)
2267 	{
2268 		buffer[j].InitData(m_context, GL_ARRAY_BUFFER, GL_DYNAMIC_COPY, buffer_size, 0 /* data */);
2269 
2270 		buffer_ids[j] = buffer[j].m_id;
2271 		offsets[j]	= offset;
2272 		strides[j]	= stride;
2273 	}
2274 
2275 	/* Prepare VAO */
2276 	GLuint vao = 0;
2277 	gl.genVertexArrays(1, &vao);
2278 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
2279 	try
2280 	{
2281 		gl.bindVertexArray(vao);
2282 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArrays");
2283 
2284 		/* - INVALID_OPERATION when <first> + <count> exceeds limits; */
2285 		{
2286 			GLsizei t_count = n_buffers;
2287 			GLuint  t_first = 0;
2288 
2289 			/* Select first so <first + count> exceeds max, avoid negative first */
2290 			if (n_buffers <= max_buffers)
2291 			{
2292 				t_first = max_buffers - n_buffers + 1;
2293 			}
2294 			else
2295 			{
2296 				t_count = max_buffers + 1;
2297 				/* first = 0; */
2298 			}
2299 
2300 			/* Test */
2301 			gl.bindVertexBuffers(t_first, t_count, buffer_ids, offsets, strides);
2302 			CHECK_ERROR(GL_INVALID_OPERATION, "BindVertexBuffers with invalid <first> + <count>");
2303 		}
2304 
2305 		/* - INVALID_OPERATION if any value in <buffers> is not zero or the name of
2306 		 * existing buffer;
2307 		 */
2308 		{
2309 			GLuint t_buffer_ids[n_buffers];
2310 
2311 			memcpy(t_buffer_ids, buffer_ids, sizeof(buffer_ids));
2312 
2313 			/* Find invalid id */
2314 			while (1)
2315 			{
2316 				if (GL_TRUE != gl.isBuffer(invalid_id))
2317 				{
2318 					break;
2319 				}
2320 
2321 				invalid_id += 1;
2322 			}
2323 
2324 			/* Invalidate the entry */
2325 			t_buffer_ids[validated_index] = invalid_id;
2326 
2327 			/* Test */
2328 			gl.bindVertexBuffers(first, count, t_buffer_ids, offsets, strides);
2329 			CHECK_ERROR(GL_INVALID_OPERATION, "BindVertexBuffers with invalid buffer id");
2330 		}
2331 
2332 		/* - INVALID_VALUE if any value in <offsets> or <strides> is less than zero. */
2333 		{
2334 			GLintptr t_offsets[n_buffers];
2335 			GLsizei  t_strides[n_buffers];
2336 
2337 			memcpy(t_offsets, offsets, sizeof(offsets));
2338 			memcpy(t_strides, strides, sizeof(strides));
2339 
2340 			/* Invalidate the entry */
2341 			t_offsets[validated_index] = -1;
2342 			t_strides[validated_index] = -1;
2343 
2344 			/* Test */
2345 			gl.bindVertexBuffers(first, count, buffer_ids, t_offsets, strides);
2346 			CHECK_ERROR(GL_INVALID_VALUE, "BindVertexBuffers with negative offset");
2347 
2348 			gl.bindVertexBuffers(first, count, buffer_ids, offsets, t_strides);
2349 			CHECK_ERROR(GL_INVALID_VALUE, "BindVertexBuffers with negative stride");
2350 		}
2351 	}
2352 	catch (const std::exception&)
2353 	{
2354 		gl.deleteVertexArrays(1, &vao);
2355 		TCU_FAIL("Unexpected error generated");
2356 	}
2357 
2358 	gl.deleteVertexArrays(1, &vao);
2359 	GLU_EXPECT_NO_ERROR(gl.getError(), "DeleteVertexArrays");
2360 
2361 	/* Set result */
2362 	m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2363 
2364 	/* Done */
2365 	return tcu::TestNode::STOP;
2366 }
2367 
2368 /** Constructor
2369  *
2370  * @param context Test context
2371  **/
FunctionalBindBuffersBaseTest(deqp::Context & context)2372 FunctionalBindBuffersBaseTest::FunctionalBindBuffersBaseTest(deqp::Context& context)
2373 	: TestCase(context, "functional_bind_buffers_base", "Verifies that BindBuffersBase works as expected")
2374 {
2375 	/* Nothing to be done */
2376 }
2377 
2378 /** Execute test
2379  *
2380  * @return tcu::TestNode::STOP
2381  **/
iterate()2382 tcu::TestNode::IterateResult FunctionalBindBuffersBaseTest::iterate()
2383 {
2384 	const Functions& gl = m_context.getRenderContext().getFunctions();
2385 
2386 #if DEBUG_ENBALE_MESSAGE_CALLBACK
2387 	gl.debugMessageCallback(debug_proc, &m_context);
2388 	GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
2389 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
2390 
2391 	for (size_t i = 0; i < s_n_buffer_tragets; ++i)
2392 	{
2393 		const GLenum	   pname_binding  = s_buffer_infos[i].m_pname_binding;
2394 		const GLenum	   pname_max	  = s_buffer_infos[i].m_pname_max;
2395 		const GLenum	   pname_max_size = s_buffer_infos[i].m_pname_max_size;
2396 		const GLenum	   target		  = s_buffer_infos[i].m_target;
2397 		const std::string& target_name	= glu::getBufferTargetStr(target).toString();
2398 
2399 		GLint max_buffers = 0;
2400 		GLint max_size	= 0;
2401 
2402 		/* Get max */
2403 		gl.getIntegerv(pname_max, &max_buffers);
2404 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2405 
2406 		/* Get max size */
2407 		gl.getIntegerv(pname_max_size, &max_size);
2408 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2409 
2410 		GLintptr buffer_size = max_size / max_buffers;
2411 
2412 		/* Storage */
2413 		std::vector<Buffer> buffer;
2414 		std::vector<GLuint> buffer_ids;
2415 
2416 		buffer.resize(max_buffers);
2417 		buffer_ids.resize(max_buffers);
2418 
2419 		/* Prepare buffers */
2420 		for (GLint j = 0; j < max_buffers; ++j)
2421 		{
2422 			buffer[j].InitData(m_context, target, GL_DYNAMIC_COPY, buffer_size, 0 /* data */);
2423 
2424 			buffer_ids[j] = buffer[j].m_id;
2425 		}
2426 
2427 		/*
2428 		 * - execute BindBufferBase to bind all buffers to tested target;
2429 		 * - inspect if bindings were modified;
2430 		 */
2431 		gl.bindBuffersBase(target, 0 /* first */, max_buffers /* count */, &buffer_ids[0]);
2432 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersBase");
2433 
2434 		for (GLint j = 0; j < max_buffers; ++j)
2435 		{
2436 			checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]);
2437 		}
2438 
2439 		/*
2440 		 *
2441 		 * - execute BindBufferBase for first half of bindings with NULL as <buffers>
2442 		 * to unbind first half of bindings for tested target;
2443 		 * - inspect if bindings were modified;
2444 		 * - execute BindBufferBase for second half of bindings with NULL as <buffers>
2445 		 * to unbind rest of bindings;
2446 		 * - inspect if bindings were modified;
2447 		 */
2448 		GLint half_index = max_buffers / 2;
2449 		gl.bindBuffersBase(target, 0 /* first */, half_index /* count */, 0);
2450 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersBase");
2451 
2452 		for (GLint j = 0; j < half_index; ++j)
2453 		{
2454 			checkBinding(m_context, pname_binding, j, target_name, 0);
2455 		}
2456 
2457 		for (GLint j = half_index; j < max_buffers; ++j)
2458 		{
2459 			checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]);
2460 		}
2461 
2462 		gl.bindBuffersBase(target, half_index /* first */, max_buffers - half_index /* count */, 0);
2463 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersBase");
2464 
2465 		for (GLint j = 0; j < max_buffers; ++j)
2466 		{
2467 			checkBinding(m_context, pname_binding, j, target_name, 0);
2468 		}
2469 
2470 		/*
2471 		 * - change <buffers> so first entry is invalid;
2472 		 * - execute BindBufferBase to bind all buffers to tested target; It is
2473 		 * expected that INVALID_OPERATION will be generated;
2474 		 * - inspect if all bindings but first were modified;
2475 		 */
2476 
2477 		/* Find invalid id */
2478 		GLuint invalid_id = 1;
2479 		while (1)
2480 		{
2481 			if (GL_TRUE != gl.isBuffer(invalid_id))
2482 			{
2483 				break;
2484 			}
2485 
2486 			invalid_id += 1;
2487 		}
2488 
2489 		buffer_ids[0] = invalid_id;
2490 
2491 		gl.bindBuffersBase(target, 0 /* first */, max_buffers /* count */, &buffer_ids[0]);
2492 		CHECK_ERROR(GL_INVALID_OPERATION, "BindBufferBase with invalid buffer id");
2493 
2494 		/* Update buffer_ids */
2495 		buffer_ids[0] = 0; /* 0 means unbound */
2496 
2497 		for (GLint j = 0; j < max_buffers; ++j)
2498 		{
2499 			checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]);
2500 		}
2501 
2502 		/*
2503 		 * - bind any buffer to first binding;
2504 		 * - execute BindBufferBase for 0 as <first>, 1 as <count> and <buffers> filled
2505 		 * with zeros to unbind 1st binding for tested target;
2506 		 * - inspect if bindings were modified;
2507 		 */
2508 		gl.bindBufferBase(target, 0, buffer[0].m_id);
2509 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferBase");
2510 		checkBinding(m_context, pname_binding, 0, target_name, buffer[0].m_id);
2511 
2512 		std::vector<GLuint> t_buffer_ids;
2513 		t_buffer_ids.resize(max_buffers);
2514 
2515 		gl.bindBuffersBase(target, 0 /* first */, 1 /* count */, &t_buffer_ids[0]);
2516 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersBase");
2517 
2518 		for (GLint j = 0; j < max_buffers; ++j)
2519 		{
2520 			checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]);
2521 		}
2522 
2523 		/* - unbind all buffers. */
2524 		gl.bindBuffersBase(target, 0 /* first */, max_buffers /* count */, 0);
2525 	}
2526 
2527 	/* Set result */
2528 	m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2529 
2530 	/* Done */
2531 	return tcu::TestNode::STOP;
2532 }
2533 
2534 /** Constructor
2535  *
2536  * @param context Test context
2537  **/
FunctionalBindBuffersRangeTest(deqp::Context & context)2538 FunctionalBindBuffersRangeTest::FunctionalBindBuffersRangeTest(deqp::Context& context)
2539 	: TestCase(context, "functional_bind_buffers_range", "Verifies that BindBuffersRange works as expected")
2540 {
2541 	/* Nothing to be done */
2542 }
2543 
2544 /** Execute test
2545  *
2546  * @return tcu::TestNode::STOP
2547  **/
iterate()2548 tcu::TestNode::IterateResult FunctionalBindBuffersRangeTest::iterate()
2549 {
2550 	const Functions& gl = m_context.getRenderContext().getFunctions();
2551 
2552 #if DEBUG_ENBALE_MESSAGE_CALLBACK
2553 	gl.debugMessageCallback(debug_proc, &m_context);
2554 	GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
2555 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
2556 
2557 	for (size_t i = 0; i < s_n_buffer_tragets; ++i)
2558 	{
2559 		const GLenum	   pname_binding  = s_buffer_infos[i].m_pname_binding;
2560 		const GLenum	   pname_max	  = s_buffer_infos[i].m_pname_max;
2561 		const GLenum	   pname_max_size = s_buffer_infos[i].m_pname_max_size;
2562 		const GLenum	   target		  = s_buffer_infos[i].m_target;
2563 		const std::string& target_name	= glu::getBufferTargetStr(target).toString();
2564 
2565 		GLint max_buffers = 0;
2566 		GLint max_size	= 0;
2567 
2568 		/* Get max */
2569 		gl.getIntegerv(pname_max, &max_buffers);
2570 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2571 
2572 		/* Get max size */
2573 		gl.getIntegerv(pname_max_size, &max_size);
2574 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2575 
2576 		GLintptr buffer_size = max_size / max_buffers;
2577 
2578 		/* Storage */
2579 		std::vector<Buffer>		buffer;
2580 		std::vector<GLuint>		buffer_ids;
2581 		std::vector<GLintptr>   offsets;
2582 		std::vector<GLsizeiptr> sizes;
2583 
2584 		buffer.resize(max_buffers);
2585 		buffer_ids.resize(max_buffers);
2586 		offsets.resize(max_buffers);
2587 		sizes.resize(max_buffers);
2588 
2589 		/* Prepare buffers */
2590 		for (GLint j = 0; j < max_buffers; ++j)
2591 		{
2592 			buffer[j].InitData(m_context, target, GL_DYNAMIC_COPY, buffer_size, 0 /* data */);
2593 
2594 			buffer_ids[j] = buffer[j].m_id;
2595 			offsets[j]	= 0;
2596 			sizes[j]	  = buffer_size;
2597 		}
2598 
2599 		/*
2600 		 * - execute BindBufferBase to bind all buffers to tested target;
2601 		 * - inspect if bindings were modified;
2602 		 */
2603 		gl.bindBuffersRange(target, 0 /* first */, max_buffers /* count */, &buffer_ids[0], &offsets[0], &sizes[0]);
2604 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersRange");
2605 
2606 		for (GLint j = 0; j < max_buffers; ++j)
2607 		{
2608 			checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]);
2609 		}
2610 
2611 		/*
2612 		 *
2613 		 * - execute BindBufferBase for first half of bindings with NULL as <buffers>
2614 		 * to unbind first half of bindings for tested target;
2615 		 * - inspect if bindings were modified;
2616 		 * - execute BindBufferBase for second half of bindings with NULL as <buffers>
2617 		 * to unbind rest of bindings;
2618 		 * - inspect if bindings were modified;
2619 		 */
2620 		GLint half_index = max_buffers / 2;
2621 		gl.bindBuffersRange(target, 0 /* first */, half_index /* count */, 0, &offsets[0], &sizes[0]);
2622 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersRange");
2623 
2624 		for (GLint j = 0; j < half_index; ++j)
2625 		{
2626 			checkBinding(m_context, pname_binding, j, target_name, 0);
2627 		}
2628 
2629 		for (GLint j = half_index; j < max_buffers; ++j)
2630 		{
2631 			checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]);
2632 		}
2633 
2634 		gl.bindBuffersRange(target, half_index /* first */, max_buffers - half_index /* count */, 0, &offsets[0],
2635 							&sizes[0]);
2636 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersRange");
2637 
2638 		for (GLint j = 0; j < max_buffers; ++j)
2639 		{
2640 			checkBinding(m_context, pname_binding, j, target_name, 0);
2641 		}
2642 
2643 		/*
2644 		 * - change <buffers> so first entry is invalid;
2645 		 * - execute BindBufferBase to bind all buffers to tested target; It is
2646 		 * expected that INVALID_OPERATION will be generated;
2647 		 * - inspect if all bindings but first were modified;
2648 		 */
2649 
2650 		/* Find invalid id */
2651 		GLuint invalid_id = 1;
2652 		while (1)
2653 		{
2654 			if (GL_TRUE != gl.isBuffer(invalid_id))
2655 			{
2656 				break;
2657 			}
2658 
2659 			invalid_id += 1;
2660 		}
2661 
2662 		buffer_ids[0] = invalid_id;
2663 
2664 		gl.bindBuffersRange(target, 0 /* first */, max_buffers /* count */, &buffer_ids[0], &offsets[0], &sizes[0]);
2665 		CHECK_ERROR(GL_INVALID_OPERATION, "BindBuffersRange with invalid buffer id");
2666 
2667 		/* Update buffer_ids */
2668 		buffer_ids[0] = 0; /* 0 means unbound */
2669 
2670 		for (GLint j = 0; j < max_buffers; ++j)
2671 		{
2672 			checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]);
2673 		}
2674 
2675 		/*
2676 		 * - bind any buffer to first binding;
2677 		 * - execute BindBufferBase for 0 as <first>, 1 as <count> and <buffers> filled
2678 		 * with zeros to unbind 1st binding for tested target;
2679 		 * - inspect if bindings were modified;
2680 		 */
2681 		gl.bindBufferBase(target, 0, buffer[0].m_id);
2682 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferBase");
2683 		checkBinding(m_context, pname_binding, 0, target_name, buffer[0].m_id);
2684 
2685 		std::vector<GLuint> t_buffer_ids;
2686 		t_buffer_ids.resize(max_buffers);
2687 
2688 		gl.bindBuffersRange(target, 0 /* first */, 1 /* count */, &t_buffer_ids[0], &offsets[0], &sizes[0]);
2689 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersRange");
2690 
2691 		for (GLint j = 0; j < max_buffers; ++j)
2692 		{
2693 			checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]);
2694 		}
2695 
2696 		/* - unbind all buffers. */
2697 		gl.bindBuffersBase(target, 0 /* first */, max_buffers /* count */, 0);
2698 	}
2699 
2700 	/* Set result */
2701 	m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2702 
2703 	/* Done */
2704 	return tcu::TestNode::STOP;
2705 }
2706 
2707 /** Constructor
2708  *
2709  * @param context Test context
2710  **/
FunctionalBindTexturesTest(deqp::Context & context)2711 FunctionalBindTexturesTest::FunctionalBindTexturesTest(deqp::Context& context)
2712 	: TestCase(context, "functional_bind_textures", "Verifies that BindTextures works as expected")
2713 {
2714 	/* Nothing to be done */
2715 }
2716 
2717 /** Execute test
2718  *
2719  * @return tcu::TestNode::STOP
2720  **/
iterate()2721 tcu::TestNode::IterateResult FunctionalBindTexturesTest::iterate()
2722 {
2723 	static const GLuint depth  = 6;
2724 	static const GLuint height = 6;
2725 	static const GLuint width  = 6;
2726 
2727 	const Functions& gl = m_context.getRenderContext().getFunctions();
2728 
2729 #if DEBUG_ENBALE_MESSAGE_CALLBACK
2730 	gl.debugMessageCallback(debug_proc, &m_context);
2731 	GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
2732 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
2733 
2734 	GLuint invalid_id   = 1; /* Start with 1, as 0 is not valid name */
2735 	GLint  max_textures = 0;
2736 
2737 	/* Get max */
2738 	gl.getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_textures);
2739 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2740 
2741 	/* Storage */
2742 	Buffer				 buffer;
2743 	std::vector<Texture> texture;
2744 	std::vector<GLuint>  texture_ids;
2745 	std::vector<GLuint>  t_texture_ids;
2746 
2747 	texture.resize(max_textures);
2748 	texture_ids.resize(max_textures);
2749 	t_texture_ids.resize(max_textures);
2750 
2751 	/* Prepare buffer */
2752 	buffer.InitData(m_context, GL_TEXTURE_BUFFER, GL_DYNAMIC_COPY, 16 /* size */, 0 /* data */);
2753 
2754 	/* Prepare textures */
2755 	for (size_t i = 0; i < s_n_texture_tragets; ++i)
2756 	{
2757 		const GLenum target = s_texture_infos[i].m_target;
2758 
2759 		if (GL_TEXTURE_BUFFER != target)
2760 		{
2761 			texture[i].InitStorage(m_context, target, 1, GL_RGBA8, width, height, depth);
2762 		}
2763 		else
2764 		{
2765 			texture[i].InitBuffer(m_context, GL_RGBA8, buffer.m_id);
2766 		}
2767 
2768 		/* Unbind */
2769 		Texture::Bind(gl, 0, target);
2770 	}
2771 
2772 	for (GLint i = s_n_texture_tragets; i < max_textures; ++i)
2773 	{
2774 		texture[i].InitStorage(m_context, GL_TEXTURE_2D, 1, GL_RGBA8, width, height, depth);
2775 	}
2776 
2777 	/* Unbind */
2778 	Texture::Bind(gl, 0, GL_TEXTURE_2D);
2779 
2780 	for (GLint i = 0; i < max_textures; ++i)
2781 	{
2782 		texture_ids[i] = texture[i].m_id;
2783 	}
2784 
2785 	/*
2786 	 * - execute BindTextures to bind all textures;
2787 	 * - inspect bindings of all texture units to verify that proper bindings were
2788 	 * set;
2789 	 */
2790 	gl.bindTextures(0, max_textures, &texture_ids[0]);
2791 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindTextures");
2792 
2793 	for (GLint i = 0; i < max_textures; ++i)
2794 	{
2795 		checkTextureBinding(m_context, getBinding(i), i, texture_ids[i]);
2796 	}
2797 
2798 	/*
2799 	 * - execute BindTextures for the first half of units with <textures> filled
2800 	 * with zeros, to unbind those units;
2801 	 * - inspect bindings of all texture units to verify that proper bindings were
2802 	 * unbound;
2803 	 */
2804 	GLint half_index = max_textures / 2;
2805 
2806 	for (GLint i = 0; i < max_textures; ++i)
2807 	{
2808 		t_texture_ids[i] = 0;
2809 	}
2810 
2811 	gl.bindTextures(0, half_index, &t_texture_ids[0]);
2812 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindTextures");
2813 
2814 	for (GLint i = 0; i < half_index; ++i)
2815 	{
2816 		checkTextureBinding(m_context, getBinding(i), i, 0);
2817 	}
2818 
2819 	for (GLint i = half_index; i < max_textures; ++i)
2820 	{
2821 		checkTextureBinding(m_context, getBinding(i), i, texture_ids[i]);
2822 	}
2823 
2824 	/*
2825 	 * - execute BindTextures for the second half of units with NULL as<textures>,
2826 	 * to unbind those units;
2827 	 * - inspect bindings of all texture units to verify that proper bindings were
2828 	 * unbound;
2829 	 */
2830 	gl.bindTextures(half_index, max_textures - half_index, 0);
2831 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindTextures");
2832 
2833 	for (GLint i = 0; i < max_textures; ++i)
2834 	{
2835 		checkTextureBinding(m_context, getBinding(i), i, 0);
2836 	}
2837 
2838 	/*
2839 	 * - modify <textures> so first entry is invalid;
2840 	 * - execute BindTextures to bind all textures; It is expected that
2841 	 * INVALID_OPERATION will be generated;
2842 	 * - inspect bindings of all texture units to verify that proper bindings were
2843 	 * set;
2844 	 */
2845 
2846 	/* Find invalid id */
2847 	while (1)
2848 	{
2849 		if (GL_TRUE != gl.isTexture(invalid_id))
2850 		{
2851 			break;
2852 		}
2853 
2854 		invalid_id += 1;
2855 	}
2856 
2857 	/* Set invalid id */
2858 	texture_ids[0] = invalid_id;
2859 
2860 	gl.bindTextures(0, max_textures, &texture_ids[0]);
2861 	CHECK_ERROR(GL_INVALID_OPERATION, "BindTextures with invalid texture id");
2862 
2863 	checkTextureBinding(m_context, getBinding(0), 0, 0);
2864 	for (GLint i = 1; i < max_textures; ++i)
2865 	{
2866 		checkTextureBinding(m_context, getBinding(i), i, texture_ids[i]);
2867 	}
2868 
2869 	/* - unbind all textures. */
2870 	gl.bindTextures(0, max_textures, 0);
2871 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindTextures");
2872 
2873 	/* Set result */
2874 	m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2875 
2876 	/* Done */
2877 	return tcu::TestNode::STOP;
2878 }
2879 
2880 /** Constructor
2881  *
2882  * @param context Test context
2883  **/
FunctionalBindSamplersTest(deqp::Context & context)2884 FunctionalBindSamplersTest::FunctionalBindSamplersTest(deqp::Context& context)
2885 	: TestCase(context, "functional_bind_samplers", "Verifies that BindSamplers works as expected")
2886 {
2887 	/* Nothing to be done */
2888 }
2889 
2890 /** Execute test
2891  *
2892  * @return tcu::TestNode::STOP
2893  **/
iterate()2894 tcu::TestNode::IterateResult FunctionalBindSamplersTest::iterate()
2895 {
2896 	const Functions& gl = m_context.getRenderContext().getFunctions();
2897 
2898 #if DEBUG_ENBALE_MESSAGE_CALLBACK
2899 	gl.debugMessageCallback(debug_proc, &m_context);
2900 	GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
2901 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
2902 
2903 	GLuint invalid_id   = 1; /* Start with 1, as 0 is not valid name */
2904 	GLint  max_samplers = 0;
2905 
2906 	/* Get max */
2907 	gl.getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_samplers);
2908 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2909 
2910 	/* Storage */
2911 	std::vector<GLuint> sampler_ids;
2912 	std::vector<GLuint> t_sampler_ids;
2913 
2914 	sampler_ids.resize(max_samplers);
2915 	t_sampler_ids.resize(max_samplers);
2916 
2917 	for (GLint i = 0; i < max_samplers; ++i)
2918 	{
2919 		t_sampler_ids[i] = 0;
2920 	}
2921 
2922 	/* Prepare samplers */
2923 	gl.genSamplers(max_samplers, &sampler_ids[0]);
2924 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenSamplers");
2925 
2926 	try
2927 	{
2928 		/* - execute BindSamplers to bind all samplers;
2929 		 * - inspect bindings to verify that proper samplers were set;
2930 		 */
2931 		gl.bindSamplers(0 /* first */, max_samplers /* count */, &sampler_ids[0]);
2932 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindSamplers");
2933 
2934 		for (GLint i = 0; i < max_samplers; ++i)
2935 		{
2936 			checkBinding(m_context, GL_SAMPLER_BINDING, i, "Sampler", sampler_ids[i]);
2937 		}
2938 
2939 		/* - execute BindSamplers for first half of bindings with <samplers> filled
2940 		 * with zeros, to unbind those samplers;
2941 		 * - inspect bindings to verify that proper samplers were unbound;
2942 		 */
2943 		GLint half_index = max_samplers / 2;
2944 
2945 		gl.bindSamplers(0, half_index, &t_sampler_ids[0]);
2946 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindSamplers");
2947 
2948 		for (GLint i = 0; i < half_index; ++i)
2949 		{
2950 			checkBinding(m_context, GL_SAMPLER_BINDING, i, "Sampler", 0);
2951 		}
2952 
2953 		for (GLint i = half_index; i < max_samplers; ++i)
2954 		{
2955 			checkBinding(m_context, GL_SAMPLER_BINDING, i, "Sampler", sampler_ids[i]);
2956 		}
2957 
2958 		/* - execute BindSamplers for second half of bindings with NULL as <samplers>,
2959 		 * to unbind those samplers;
2960 		 * - inspect bindings to verify that proper samplers were unbound;
2961 		 */
2962 		gl.bindSamplers(half_index, max_samplers - half_index, 0);
2963 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindSamplers");
2964 
2965 		for (GLint i = 0; i < max_samplers; ++i)
2966 		{
2967 			checkBinding(m_context, GL_SAMPLER_BINDING, i, "Sampler", 0);
2968 		}
2969 
2970 		/* - modify <samplers> so first entry is invalid;
2971 		 * - execute BindSamplers to bind all samplers; It is expected that
2972 		 * INVALID_OPERATION will be generated;
2973 		 * - inspect bindings to verify that proper samplers were set;
2974 		 */
2975 
2976 		/* Find invalid id */
2977 		while (1)
2978 		{
2979 			if (GL_TRUE != gl.isSampler(invalid_id))
2980 			{
2981 				break;
2982 			}
2983 
2984 			invalid_id += 1;
2985 		}
2986 
2987 		/* Prepare ids */
2988 		t_sampler_ids[0] = invalid_id;
2989 
2990 		for (GLint i = 1; i < max_samplers; ++i)
2991 		{
2992 			t_sampler_ids[i] = sampler_ids[i];
2993 		}
2994 
2995 		/* Bind */
2996 		gl.bindSamplers(0, max_samplers, &t_sampler_ids[0]);
2997 		CHECK_ERROR(GL_INVALID_OPERATION, "BindSamplers with invalid sampler id");
2998 
2999 		/* Set 0 for invalid entry */
3000 		t_sampler_ids[0] = 0;
3001 
3002 		for (GLint i = 0; i < max_samplers; ++i)
3003 		{
3004 			checkBinding(m_context, GL_SAMPLER_BINDING, i, "Sampler", t_sampler_ids[i]);
3005 		}
3006 
3007 		/* - unbind all samplers. */
3008 		gl.bindSamplers(0, max_samplers, 0);
3009 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindSamplers");
3010 	}
3011 	catch (const std::exception&)
3012 	{
3013 		gl.deleteSamplers(max_samplers, &sampler_ids[0]);
3014 
3015 		TCU_FAIL("Invalid error generated");
3016 	}
3017 
3018 	/* Delete samplers */
3019 	gl.deleteSamplers(max_samplers, &sampler_ids[0]);
3020 
3021 	/* Set result */
3022 	m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3023 
3024 	/* Done */
3025 	return tcu::TestNode::STOP;
3026 }
3027 
3028 /** Constructor
3029  *
3030  * @param context Test context
3031  **/
FunctionalBindImageTexturesTest(deqp::Context & context)3032 FunctionalBindImageTexturesTest::FunctionalBindImageTexturesTest(deqp::Context& context)
3033 	: TestCase(context, "functional_bind_image_textures", "Verifies that BindImageTextures works as expected")
3034 {
3035 	/* Nothing to be done */
3036 }
3037 
3038 /** Execute test
3039  *
3040  * @return tcu::TestNode::STOP
3041  **/
iterate()3042 tcu::TestNode::IterateResult FunctionalBindImageTexturesTest::iterate()
3043 {
3044 	static const GLuint depth  = 6;
3045 	static const GLuint height = 6;
3046 	static const GLuint width  = 6;
3047 
3048 	const Functions& gl = m_context.getRenderContext().getFunctions();
3049 
3050 #if DEBUG_ENBALE_MESSAGE_CALLBACK
3051 	gl.debugMessageCallback(debug_proc, &m_context);
3052 	GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
3053 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
3054 
3055 	GLuint invalid_id   = 1; /* Start with 1, as 0 is not valid name */
3056 	GLint  max_textures = 0;
3057 
3058 	/* Get max */
3059 	gl.getIntegerv(GL_MAX_IMAGE_UNITS, &max_textures);
3060 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3061 
3062 	/* Storage */
3063 	Buffer				 buffer;
3064 	std::vector<Texture> texture;
3065 	std::vector<GLuint>  texture_ids;
3066 	std::vector<GLuint>  t_texture_ids;
3067 
3068 	texture.resize(max_textures);
3069 	texture_ids.resize(max_textures);
3070 	t_texture_ids.resize(max_textures);
3071 
3072 	/* Prepare buffer */
3073 	buffer.InitData(m_context, GL_TEXTURE_BUFFER, GL_DYNAMIC_COPY, 16 /* size */, 0 /* data */);
3074 
3075 	/* Prepare textures */
3076 	for (GLint i = 0; i < (GLint)s_n_texture_tragets; ++i)
3077 	{
3078 		const GLenum target = s_texture_infos[i].m_target;
3079 
3080 		if (i >= max_textures)
3081 		{
3082 			break;
3083 		}
3084 
3085 		if (GL_TEXTURE_BUFFER != target)
3086 		{
3087 			texture[i].InitStorage(m_context, target, 1, GL_RGBA8, width, height, depth);
3088 		}
3089 		else
3090 		{
3091 			texture[i].InitBuffer(m_context, GL_RGBA8, buffer.m_id);
3092 		}
3093 
3094 		/* Unbind */
3095 		Texture::Bind(gl, 0, target);
3096 	}
3097 
3098 	for (GLint i = (GLint)s_n_texture_tragets; i < max_textures; ++i)
3099 	{
3100 		texture[i].InitStorage(m_context, GL_TEXTURE_2D, 1, GL_RGBA8, width, height, depth);
3101 	}
3102 
3103 	/* Unbind */
3104 	Texture::Bind(gl, 0, GL_TEXTURE_2D);
3105 
3106 	for (GLint i = 0; i < max_textures; ++i)
3107 	{
3108 		texture_ids[i] = texture[i].m_id;
3109 	}
3110 
3111 	/*
3112 	 * - execute BindImageTextures to bind all images;
3113 	 * - inspect bindings to verify that proper images were set;
3114 	 */
3115 	gl.bindImageTextures(0, max_textures, &texture_ids[0]);
3116 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTextures");
3117 
3118 	for (GLint i = 0; i < max_textures; ++i)
3119 	{
3120 		checkBinding(m_context, GL_IMAGE_BINDING_NAME, i, "Image unit", texture_ids[i]);
3121 	}
3122 
3123 	/*
3124 	 * - execute BindTextures for the first half of units with <textures> filled
3125 	 * with zeros, to unbind those units;
3126 	 * - inspect bindings of all texture units to verify that proper bindings were
3127 	 * unbound;
3128 	 */
3129 	GLint half_index = max_textures / 2;
3130 
3131 	for (GLint i = 0; i < max_textures; ++i)
3132 	{
3133 		t_texture_ids[i] = 0;
3134 	}
3135 
3136 	gl.bindImageTextures(0, half_index, &t_texture_ids[0]);
3137 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTextures");
3138 
3139 	for (GLint i = 0; i < half_index; ++i)
3140 	{
3141 		checkBinding(m_context, GL_IMAGE_BINDING_NAME, i, "Image unit", 0);
3142 	}
3143 
3144 	for (GLint i = half_index; i < max_textures; ++i)
3145 	{
3146 		checkBinding(m_context, GL_IMAGE_BINDING_NAME, i, "Image unit", texture_ids[i]);
3147 	}
3148 
3149 	/*
3150 	 * - execute BindTextures for the second half of units with NULL as<textures>,
3151 	 * to unbind those units;
3152 	 * - inspect bindings of all texture units to verify that proper bindings were
3153 	 * unbound;
3154 	 */
3155 	gl.bindImageTextures(half_index, max_textures - half_index, 0);
3156 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTextures");
3157 
3158 	for (GLint i = 0; i < max_textures; ++i)
3159 	{
3160 		checkBinding(m_context, GL_IMAGE_BINDING_NAME, i, "Image unit", 0);
3161 	}
3162 
3163 	/*
3164 	 * - modify <textures> so first entry is invalid;
3165 	 * - execute BindTextures to bind all textures; It is expected that
3166 	 * INVALID_OPERATION will be generated;
3167 	 * - inspect bindings of all texture units to verify that proper bindings were
3168 	 * set;
3169 	 */
3170 
3171 	/* Find invalid id */
3172 	while (1)
3173 	{
3174 		if (GL_TRUE != gl.isTexture(invalid_id))
3175 		{
3176 			break;
3177 		}
3178 
3179 		invalid_id += 1;
3180 	}
3181 
3182 	/* Set invalid id */
3183 	texture_ids[0] = invalid_id;
3184 
3185 	gl.bindImageTextures(0, max_textures, &texture_ids[0]);
3186 	CHECK_ERROR(GL_INVALID_OPERATION, "BindImageTextures with invalid texture id");
3187 
3188 	checkBinding(m_context, GL_IMAGE_BINDING_NAME, 0, "Image unit", 0);
3189 	for (GLint i = 1; i < max_textures; ++i)
3190 	{
3191 		checkBinding(m_context, GL_IMAGE_BINDING_NAME, i, "Image unit", texture_ids[i]);
3192 	}
3193 
3194 	/* - unbind all textures. */
3195 	gl.bindImageTextures(0, max_textures, 0);
3196 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTextures");
3197 
3198 	/* Set result */
3199 	m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3200 
3201 	/* Done */
3202 	return tcu::TestNode::STOP;
3203 }
3204 
3205 /** Constructor
3206  *
3207  * @param context Test context
3208  **/
FunctionalBindVertexBuffersTest(deqp::Context & context)3209 FunctionalBindVertexBuffersTest::FunctionalBindVertexBuffersTest(deqp::Context& context)
3210 	: TestCase(context, "functional_bind_vertex_buffers", "Verifies that BindVertexBuffers works as expected")
3211 {
3212 	/* Nothing to be done */
3213 }
3214 
3215 /** Execute test
3216  *
3217  * @return tcu::TestNode::STOP
3218  **/
iterate()3219 tcu::TestNode::IterateResult FunctionalBindVertexBuffersTest::iterate()
3220 {
3221 	const Functions& gl = m_context.getRenderContext().getFunctions();
3222 
3223 #if DEBUG_ENBALE_MESSAGE_CALLBACK
3224 	gl.debugMessageCallback(debug_proc, &m_context);
3225 	GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
3226 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
3227 
3228 	static const GLintptr buffer_size = 16;
3229 	static const GLintptr offset	  = 4;
3230 	static const GLsizei  stride	  = 4;
3231 
3232 	GLuint invalid_id  = 1; /* Start with 1, as 0 is not valid name */
3233 	GLint  max_buffers = 0;
3234 
3235 	/* Get max */
3236 	gl.getIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &max_buffers);
3237 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3238 
3239 	/* Storage */
3240 	std::vector<Buffer>   buffer;
3241 	std::vector<GLuint>   buffer_ids;
3242 	std::vector<GLintptr> offsets;
3243 	std::vector<GLsizei>  strides;
3244 	std::vector<GLuint>   t_buffer_ids;
3245 
3246 	buffer.resize(max_buffers);
3247 	buffer_ids.resize(max_buffers);
3248 	offsets.resize(max_buffers);
3249 	strides.resize(max_buffers);
3250 	t_buffer_ids.resize(max_buffers);
3251 
3252 	/* Prepare buffers */
3253 	for (GLint i = 0; i < max_buffers; ++i)
3254 	{
3255 		buffer[i].InitData(m_context, GL_ARRAY_BUFFER, GL_DYNAMIC_COPY, buffer_size, 0 /* data */);
3256 
3257 		buffer_ids[i]   = buffer[i].m_id;
3258 		offsets[i]		= offset;
3259 		strides[i]		= stride;
3260 		t_buffer_ids[i] = 0;
3261 	}
3262 
3263 	GLuint vao = 0;
3264 	gl.genVertexArrays(1, &vao);
3265 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
3266 	try
3267 	{
3268 		gl.bindVertexArray(vao);
3269 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArrays");
3270 
3271 		/* - execute BindVertexBuffers to bind all buffer;
3272 		 * - inspect bindings to verify that proper buffers were set;
3273 		 */
3274 		gl.bindVertexBuffers(0, max_buffers, &buffer_ids[0], &offsets[0], &strides[0]);
3275 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexBuffers");
3276 
3277 		for (GLint i = 0; i < max_buffers; ++i)
3278 		{
3279 			checkVertexAttribBinding(m_context, i, buffer_ids[i]);
3280 		}
3281 
3282 		/* - execute BindVertexBuffers for first half of bindings with <buffers> filled
3283 		 * with zeros, to unbind those buffers;
3284 		 * - inspect bindings to verify that proper buffers were unbound;
3285 		 */
3286 		GLint half_index = max_buffers / 2;
3287 
3288 		gl.bindVertexBuffers(0, half_index, &t_buffer_ids[0], &offsets[0], &strides[0]);
3289 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexBuffers");
3290 
3291 		for (GLint i = 0; i < half_index; ++i)
3292 		{
3293 			checkVertexAttribBinding(m_context, i, 0);
3294 		}
3295 
3296 		for (GLint i = half_index; i < max_buffers; ++i)
3297 		{
3298 			checkVertexAttribBinding(m_context, i, buffer_ids[i]);
3299 		}
3300 
3301 		/* - execute BindVertexBuffers for second half of bindings with NULL as
3302 		 * <buffers>, to unbind those buffers;
3303 		 * - inspect bindings to verify that proper buffers were unbound;
3304 		 */
3305 		gl.bindVertexBuffers(half_index, max_buffers - half_index, 0, &offsets[0], &strides[0]);
3306 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexBuffers");
3307 
3308 		for (GLint i = 0; i < max_buffers; ++i)
3309 		{
3310 			checkVertexAttribBinding(m_context, i, 0);
3311 		}
3312 
3313 		/* - modify <buffers> so first entry is invalid;
3314 		 * - execute BindVertexBuffers to bind all buffers; It is expected that
3315 		 * INVALID_OPERATION will be generated;
3316 		 * - inspect bindings to verify that proper buffers were set;
3317 		 */
3318 
3319 		/* Find invalid id */
3320 		while (1)
3321 		{
3322 			if (GL_TRUE != gl.isBuffer(invalid_id))
3323 			{
3324 				break;
3325 			}
3326 
3327 			invalid_id += 1;
3328 		}
3329 
3330 		buffer_ids[0] = invalid_id;
3331 		gl.bindVertexBuffers(0, max_buffers, &buffer_ids[0], &offsets[0], &strides[0]);
3332 		CHECK_ERROR(GL_INVALID_OPERATION, "BindVertexBuffers with invalid id");
3333 
3334 		checkVertexAttribBinding(m_context, 0, 0);
3335 		for (GLint i = 1; i < max_buffers; ++i)
3336 		{
3337 			checkVertexAttribBinding(m_context, i, buffer_ids[i]);
3338 		}
3339 
3340 		/* - unbind all buffers. */
3341 		gl.bindVertexBuffers(0, max_buffers, 0, &offsets[0], &strides[0]);
3342 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexBuffers");
3343 	}
3344 	catch (const std::exception&)
3345 	{
3346 		gl.deleteVertexArrays(1, &vao);
3347 
3348 		TCU_FAIL("Unexpected error generated");
3349 	}
3350 
3351 	gl.deleteVertexArrays(1, &vao);
3352 	GLU_EXPECT_NO_ERROR(gl.getError(), "DeleteVertexArrays");
3353 
3354 	/* Set result */
3355 	m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3356 
3357 	/* Done */
3358 	return tcu::TestNode::STOP;
3359 }
3360 
3361 /** Constructor
3362  *
3363  * @param context Test context
3364  **/
DispatchBindBuffersBaseTest(deqp::Context & context)3365 DispatchBindBuffersBaseTest::DispatchBindBuffersBaseTest(deqp::Context& context)
3366 	: TestCase(context, "dispatch_bind_buffers_base", "Tests BindBuffersBase with dispatch command")
3367 {
3368 	/* Nothing to be done */
3369 }
3370 
3371 /** Execute test
3372  *
3373  * @return tcu::TestNode::STOP
3374  **/
iterate()3375 tcu::TestNode::IterateResult DispatchBindBuffersBaseTest::iterate()
3376 {
3377 	static const GLchar* cs = "#version 440 core\n"
3378 							  "\n"
3379 							  "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
3380 							  "\n"
3381 							  "UBO_LIST\n"
3382 							  "layout (std140, binding = 0) buffer SSB {\n"
3383 							  "    vec4 sum;\n"
3384 							  "} ssb;\n"
3385 							  "\n"
3386 							  "void main()\n"
3387 							  "{\n"
3388 							  "    ssb.sum = SUM_LIST;\n"
3389 							  "}\n"
3390 							  "\n";
3391 
3392 	static const GLchar* ubo = "layout (std140, binding = XXX) uniform BXXX { vec4 data; } bXXX;";
3393 
3394 	static const GLintptr buffer_size = 4 * sizeof(GLfloat);
3395 
3396 	const Functions& gl = m_context.getRenderContext().getFunctions();
3397 
3398 	bool test_result = true;
3399 
3400 #if DEBUG_ENBALE_MESSAGE_CALLBACK
3401 	gl.debugMessageCallback(debug_proc, &m_context);
3402 	GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
3403 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
3404 
3405 	GLint   max_buffers = 0;
3406 	GLfloat sum[4]		= { 0.0f, 0.0f, 0.0f, 0.0f };
3407 
3408 	/* Get max */
3409 	gl.getIntegerv(GL_MAX_COMPUTE_UNIFORM_BLOCKS, &max_buffers);
3410 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3411 
3412 	/* UBO */
3413 	/* Storage */
3414 	std::vector<Buffer> uni_buffer;
3415 	std::vector<GLuint> uni_buffer_ids;
3416 
3417 	uni_buffer.resize(max_buffers);
3418 	uni_buffer_ids.resize(max_buffers);
3419 
3420 	/* Prepare buffers */
3421 	for (GLint i = 0; i < max_buffers; ++i)
3422 	{
3423 		const GLfloat data[4] = {
3424 			(GLfloat)(i * 4 + 0), (GLfloat)(i * 4 + 1), (GLfloat)(i * 4 + 2), (GLfloat)(i * 4 + 3),
3425 		};
3426 
3427 		sum[0] += data[0];
3428 		sum[1] += data[1];
3429 		sum[2] += data[2];
3430 		sum[3] += data[3];
3431 
3432 		uni_buffer[i].InitData(m_context, GL_UNIFORM_BUFFER, GL_DYNAMIC_COPY, buffer_size, data);
3433 
3434 		uni_buffer_ids[i] = uni_buffer[i].m_id;
3435 	}
3436 
3437 	gl.bindBuffersBase(GL_UNIFORM_BUFFER, 0 /* first */, max_buffers /* count */, &uni_buffer_ids[0]);
3438 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersBase");
3439 
3440 	/* SSBO */
3441 	Buffer ssb_buffer;
3442 	ssb_buffer.InitData(m_context, GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, buffer_size, 0 /* data */);
3443 
3444 	ssb_buffer.BindBase(0);
3445 
3446 	/* Prepare program */
3447 	size_t		ubo_position = 0;
3448 	size_t		sum_position = 0;
3449 	std::string cs_source	= cs;
3450 	for (GLint i = 0; i < max_buffers; ++i)
3451 	{
3452 		size_t ubo_start_position = ubo_position;
3453 		size_t sum_start_position = sum_position;
3454 
3455 		GLchar index[16];
3456 
3457 		sprintf(index, "%d", i);
3458 
3459 		/* Add entry to ubo list */
3460 		replaceToken("UBO_LIST", ubo_position, "UBO\nUBO_LIST", cs_source);
3461 		ubo_position = ubo_start_position;
3462 
3463 		replaceToken("UBO", ubo_position, ubo, cs_source);
3464 		ubo_position = ubo_start_position;
3465 
3466 		replaceToken("XXX", ubo_position, index, cs_source);
3467 		replaceToken("XXX", ubo_position, index, cs_source);
3468 		replaceToken("XXX", ubo_position, index, cs_source);
3469 
3470 		/* Add entry to sum list */
3471 		replaceToken("SUM_LIST", sum_position, "bXXX.data + SUM_LIST", cs_source);
3472 		sum_position = sum_start_position;
3473 
3474 		replaceToken("XXX", sum_position, index, cs_source);
3475 	}
3476 
3477 	/* Remove token for lists */
3478 	replaceToken(" + SUM_LIST", sum_position, "", cs_source);
3479 	replaceToken("UBO_LIST", ubo_position, "", cs_source);
3480 
3481 	Program program(m_context);
3482 	program.Init(cs_source.c_str(), "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
3483 
3484 	program.Use();
3485 
3486 	gl.dispatchCompute(1, 1, 1);
3487 	GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
3488 
3489 	gl.memoryBarrier(GL_ALL_BARRIER_BITS);
3490 	GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3491 
3492 	GLfloat* result = (GLfloat*)gl.mapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY);
3493 	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
3494 
3495 	if (0 != memcmp(result, sum, 4 * sizeof(GLfloat)))
3496 	{
3497 		test_result = false;
3498 	}
3499 
3500 	gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
3501 	gl.getError(); /* Ignore error */
3502 
3503 	/* Set result */
3504 	if (true == test_result)
3505 	{
3506 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3507 	}
3508 	else
3509 	{
3510 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3511 	}
3512 
3513 	/* Done */
3514 	return tcu::TestNode::STOP;
3515 }
3516 
3517 /** Constructor
3518  *
3519  * @param context Test context
3520  **/
DispatchBindBuffersRangeTest(deqp::Context & context)3521 DispatchBindBuffersRangeTest::DispatchBindBuffersRangeTest(deqp::Context& context)
3522 	: TestCase(context, "dispatch_bind_buffers_range", "Tests BindBuffersRange with dispatch command")
3523 {
3524 	/* Nothing to be done */
3525 }
3526 
3527 /** Execute test
3528  *
3529  * @return tcu::TestNode::STOP
3530  **/
iterate()3531 tcu::TestNode::IterateResult DispatchBindBuffersRangeTest::iterate()
3532 {
3533 	static const GLchar* cs = "#version 440 core\n"
3534 							  "\n"
3535 							  "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
3536 							  "\n"
3537 							  "layout (std140, binding = 0) uniform B0 { int data; } b0;"
3538 							  "layout (std140, binding = 1) uniform B1 { int data; } b1;"
3539 							  "layout (std140, binding = 2) uniform B2 { int data; } b2;"
3540 							  "layout (std140, binding = 3) uniform B3 { int data; } b3;"
3541 							  "\n"
3542 							  "layout (std140, binding = 0) buffer SSB {\n"
3543 							  "    int sum;\n"
3544 							  "} ssb;\n"
3545 							  "\n"
3546 							  "void main()\n"
3547 							  "{\n"
3548 							  "    //ssb.sum = b1.data;// + b1.data + b2.data + b3.data;\n"
3549 							  "    ssb.sum = b0.data + b1.data + b2.data + b3.data;\n"
3550 							  "}\n"
3551 							  "\n";
3552 
3553 	static const GLint  data[]	= { 0x00010001, 0x01000100 };
3554 	static const size_t n_buffers = 4;
3555 	static const GLint  sum		  = 0x02020202;
3556 
3557 	const Functions& gl = m_context.getRenderContext().getFunctions();
3558 
3559 	bool test_result = true;
3560 
3561 #if DEBUG_ENBALE_MESSAGE_CALLBACK
3562 	gl.debugMessageCallback(debug_proc, &m_context);
3563 	GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
3564 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
3565 
3566 	/* UBO */
3567 	GLint offset_alignment = 0;
3568 
3569 	gl.getIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &offset_alignment);
3570 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3571 
3572 	/* Storage */
3573 	Buffer				 uni_buffer;
3574 	GLuint				 uni_buffer_ids[n_buffers];
3575 	std::vector<GLubyte> uni_data;
3576 	GLintptr			 uni_offsets[n_buffers];
3577 	GLintptr			 uni_sizes[n_buffers];
3578 
3579 	const size_t buffer_size = (n_buffers - 1) * offset_alignment + sizeof(GLint);
3580 	uni_data.resize(buffer_size);
3581 
3582 	for (size_t i = 0; i < buffer_size; ++i)
3583 	{
3584 		uni_data[i] = 0xaa;
3585 	}
3586 
3587 	for (size_t i = 0; i < n_buffers; ++i)
3588 	{
3589 		void*		dst = &uni_data[i * offset_alignment];
3590 		const void* src = &data[(i % 2)];
3591 
3592 		memcpy(dst, src, sizeof(GLint));
3593 	}
3594 
3595 	uni_buffer.InitData(m_context, GL_UNIFORM_BUFFER, GL_DYNAMIC_COPY, buffer_size, &uni_data[0]);
3596 
3597 	for (size_t i = 0; i < n_buffers; ++i)
3598 	{
3599 		uni_buffer_ids[i] = uni_buffer.m_id;
3600 		uni_offsets[i]	= i * offset_alignment;
3601 		uni_sizes[i]	  = sizeof(GLint);
3602 	}
3603 
3604 	gl.bindBuffersRange(GL_UNIFORM_BUFFER, 0 /* first */, n_buffers /* count */, &uni_buffer_ids[0], &uni_offsets[0],
3605 						&uni_sizes[0]);
3606 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersRange");
3607 
3608 	/* SSBO */
3609 	Buffer ssb_buffer;
3610 	ssb_buffer.InitData(m_context, GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, sizeof(GLint), 0 /* data */);
3611 
3612 	ssb_buffer.BindBase(0);
3613 
3614 	/* Prepare program */
3615 	Program program(m_context);
3616 	program.Init(cs, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
3617 
3618 	program.Use();
3619 
3620 	gl.dispatchCompute(1, 1, 1);
3621 	GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
3622 
3623 	gl.memoryBarrier(GL_ALL_BARRIER_BITS);
3624 	GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3625 
3626 	GLint* result = (GLint*)gl.mapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY);
3627 	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
3628 
3629 	if (0 != memcmp(result, &sum, sizeof(sum)))
3630 	{
3631 		test_result = false;
3632 	}
3633 
3634 	gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
3635 	gl.getError(); /* Ignore error */
3636 
3637 	/* Set result */
3638 	if (true == test_result)
3639 	{
3640 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3641 	}
3642 	else
3643 	{
3644 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3645 	}
3646 
3647 	/* Done */
3648 	return tcu::TestNode::STOP;
3649 }
3650 
3651 /** Constructor
3652  *
3653  * @param context Test context
3654  **/
DispatchBindTexturesTest(deqp::Context & context)3655 DispatchBindTexturesTest::DispatchBindTexturesTest(deqp::Context& context)
3656 	: TestCase(context, "dispatch_bind_textures", "Tests BindTextures with dispatch command")
3657 {
3658 	/* Nothing to be done */
3659 }
3660 
3661 /** Execute test
3662  *
3663  * @return tcu::TestNode::STOP
3664  **/
iterate()3665 tcu::TestNode::IterateResult DispatchBindTexturesTest::iterate()
3666 {
3667 	static const GLchar* cs = "#version 440 core\n"
3668 							  "\n"
3669 							  "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
3670 							  "\n"
3671 							  "SAMPLER_LIST\n"
3672 							  "layout (std140, binding = 0) buffer SSB {\n"
3673 							  "    uint sum;\n"
3674 							  "} ssb;\n"
3675 							  "\n"
3676 							  "void main()\n"
3677 							  "{\n"
3678 							  "    uvec4 sum = SUM_LIST;\n"
3679 							  "    ssb.sum = sum.r\n;"
3680 							  "}\n"
3681 							  "\n";
3682 
3683 	static const GLchar* sampler = "layout (location = XXX) uniform SAMPLER sXXX;";
3684 
3685 	static const GLchar* sampling[] = {
3686 		"texture(sXXX, COORDS)", "texture(sXXX, COORDS)",		"texture(sXXX, COORDS)",	  "texture(sXXX, COORDS)",
3687 		"texture(sXXX, COORDS)", "texelFetch(sXXX, COORDS)",	"texture(sXXX, COORDS)",	  "texture(sXXX, COORDS)",
3688 		"texture(sXXX, COORDS)", "texelFetch(sXXX, COORDS, 0)", "texelFetch(sXXX, COORDS, 0)"
3689 	};
3690 
3691 	static const GLchar* samplers[] = { "usampler1D",	 "usampler1DArray", "usampler2D",		 "usampler2DArray",
3692 										"usampler3D",	 "usamplerBuffer",  "usamplerCube",	 "usamplerCubeArray",
3693 										"usampler2DRect", "usampler2DMS",	"usampler2DMSArray" };
3694 
3695 	static const GLchar* coordinates[] = {
3696 		"0.5f",
3697 		"vec2(0.5f, 0.0f)",
3698 		"vec2(0.5f, 0.5f)",
3699 		"vec3(0.5f, 0.5f, 0.0f)",
3700 		"vec3(0.5f, 0.5f, 0.5f)",
3701 		"0",
3702 		"vec3(0.5f, 0.5f, 0.5f)",
3703 		"vec4(0.5f, 0.5f, 0.5f, 0.0f)",
3704 		"vec2(0.5f, 0.5f)",
3705 		"ivec2(0, 0)",
3706 		"ivec3(0, 0, 0)",
3707 	};
3708 
3709 	static const GLuint depth  = 6;
3710 	static const GLuint height = 6;
3711 	static const GLuint width  = 6;
3712 
3713 	const Functions& gl = m_context.getRenderContext().getFunctions();
3714 
3715 	bool test_result = true;
3716 
3717 #if DEBUG_ENBALE_MESSAGE_CALLBACK
3718 	gl.debugMessageCallback(debug_proc, &m_context);
3719 	GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
3720 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
3721 
3722 	GLint  max_textures		 = 0;
3723 	GLint  max_image_samples = 0;
3724 	GLuint sum				 = 0;
3725 
3726 	/* Get max */
3727 	gl.getIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &max_textures);
3728 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3729 
3730 	/* Check if load/store from multisampled images is supported */
3731 	gl.getIntegerv(GL_MAX_IMAGE_SAMPLES, &max_image_samples);
3732 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3733 
3734 	/* Textures */
3735 	/* Storage */
3736 	std::vector<Texture> texture;
3737 	std::vector<GLuint>  texture_ids;
3738 	Buffer				 texture_buffer;
3739 
3740 	texture.resize(max_textures);
3741 	texture_ids.resize(max_textures);
3742 
3743 	/* Prepare */
3744 	for (GLint i = 0; i < max_textures; ++i)
3745 	{
3746 		GLenum target = getTarget(i);
3747 		if (target >= GL_TEXTURE_2D_MULTISAMPLE && max_image_samples == 0)
3748 			target = GL_TEXTURE_2D;
3749 
3750 		GLuint data[width * height * depth];
3751 
3752 		for (GLuint j = 0; j < width * height * depth; ++j)
3753 		{
3754 			data[j] = i;
3755 		}
3756 
3757 		sum += i;
3758 
3759 		bool is_array = false;
3760 
3761 		switch (target)
3762 		{
3763 		case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
3764 			is_array = true;
3765 		/* Intentional fallthrough */
3766 
3767 		case GL_TEXTURE_2D_MULTISAMPLE:
3768 			texture[i].InitStorage(m_context, target, 1, GL_R32UI, width, height, depth);
3769 			fillMSTexture(m_context, texture[i].m_id, i, is_array);
3770 			break;
3771 
3772 		case GL_TEXTURE_BUFFER:
3773 			texture_buffer.InitData(m_context, GL_TEXTURE_BUFFER, GL_DYNAMIC_COPY, sizeof(data), data);
3774 			texture[i].InitBuffer(m_context, GL_R32UI, texture_buffer.m_id);
3775 			break;
3776 
3777 		default:
3778 			texture[i].InitStorage(m_context, target, 1, GL_R32UI, width, height, depth);
3779 			Texture::Bind(gl, texture[i].m_id, target);
3780 			Texture::SubImage(gl, target, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height, depth,
3781 							  GL_RED_INTEGER, GL_UNSIGNED_INT, &data);
3782 			gl.texParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3783 			gl.texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3784 			break;
3785 		}
3786 
3787 		/* Clean */
3788 		Texture::Bind(gl, 0, target);
3789 
3790 		texture_ids[i] = texture[i].m_id;
3791 	}
3792 
3793 	gl.bindTextures(0 /* first */, max_textures /* count */, &texture_ids[0]);
3794 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindTextures");
3795 
3796 	/* SSBO */
3797 	Buffer ssb_buffer;
3798 	ssb_buffer.InitData(m_context, GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, sizeof(GLuint), 0 /* data */);
3799 
3800 	ssb_buffer.BindBase(0);
3801 
3802 	/* Prepare program */
3803 	size_t		sam_position	 = 0;
3804 	size_t		sum_position	 = 0;
3805 	std::string cs_source		 = cs;
3806 	GLint		max_target_index = (GLint)(max_image_samples > 0 ? s_n_texture_tragets : s_n_texture_tragets - 2);
3807 	for (GLint i = 0; i < max_textures; ++i)
3808 	{
3809 		size_t sam_start_position = sam_position;
3810 		size_t sum_start_position = sum_position;
3811 
3812 		GLchar index[16];
3813 
3814 		sprintf(index, "%d", i);
3815 
3816 		const GLchar* coords		= 0;
3817 		const GLchar* sampler_type  = 0;
3818 		const GLchar* sampling_code = 0;
3819 
3820 		if (i < max_target_index)
3821 		{
3822 			coords		  = coordinates[i];
3823 			sampler_type  = samplers[i];
3824 			sampling_code = sampling[i];
3825 		}
3826 		else
3827 		{
3828 			coords		  = coordinates[2]; /* vec2(0.5f, 0.5f) */
3829 			sampler_type  = samplers[2];	/* usampler2D */
3830 			sampling_code = sampling[2];	/* texture(sXXX, COORDS) */
3831 		}
3832 
3833 		/* Add entry to ubo list */
3834 		replaceToken("SAMPLER_LIST", sam_position, "SAMPLER\nSAMPLER_LIST", cs_source);
3835 		sam_position = sam_start_position;
3836 
3837 		replaceToken("SAMPLER", sam_position, sampler, cs_source);
3838 		sam_position = sam_start_position;
3839 
3840 		replaceToken("XXX", sam_position, index, cs_source);
3841 		replaceToken("SAMPLER", sam_position, sampler_type, cs_source);
3842 		replaceToken("XXX", sam_position, index, cs_source);
3843 
3844 		/* Add entry to sum list */
3845 		replaceToken("SUM_LIST", sum_position, "SAMPLING + SUM_LIST", cs_source);
3846 		sum_position = sum_start_position;
3847 
3848 		replaceToken("SAMPLING", sum_position, sampling_code, cs_source);
3849 		sum_position = sum_start_position;
3850 
3851 		replaceToken("XXX", sum_position, index, cs_source);
3852 		replaceToken("COORDS", sum_position, coords, cs_source);
3853 	}
3854 
3855 	/* Remove token for lists */
3856 	replaceToken(" + SUM_LIST", sum_position, "", cs_source);
3857 	replaceToken("SAMPLER_LIST", sam_position, "", cs_source);
3858 
3859 	Program program(m_context);
3860 	program.Init(cs_source.c_str(), "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
3861 
3862 	program.Use();
3863 
3864 	/* Set samplers */
3865 	for (GLint i = 0; i < max_textures; ++i)
3866 	{
3867 		gl.uniform1i(i, i);
3868 		GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
3869 	}
3870 
3871 	gl.dispatchCompute(1, 1, 1);
3872 	GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
3873 
3874 	gl.memoryBarrier(GL_ALL_BARRIER_BITS);
3875 	GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3876 
3877 	GLuint* result = (GLuint*)gl.mapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY);
3878 	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
3879 
3880 	if (0 != memcmp(result, &sum, sizeof(sum)))
3881 	{
3882 		test_result = false;
3883 	}
3884 
3885 	gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
3886 	gl.getError(); /* Ignore error */
3887 
3888 	/* Set result */
3889 	if (true == test_result)
3890 	{
3891 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3892 	}
3893 	else
3894 	{
3895 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3896 	}
3897 
3898 	/* Done */
3899 	return tcu::TestNode::STOP;
3900 }
3901 
3902 /** Constructor
3903  *
3904  * @param context Test context
3905  **/
DispatchBindImageTexturesTest(deqp::Context & context)3906 DispatchBindImageTexturesTest::DispatchBindImageTexturesTest(deqp::Context& context)
3907 	: TestCase(context, "dispatch_bind_image_textures", "Tests BindImageTextures with dispatch command")
3908 {
3909 	/* Nothing to be done */
3910 }
3911 
3912 /** Execute test
3913  *
3914  * @return tcu::TestNode::STOP
3915  **/
iterate()3916 tcu::TestNode::IterateResult DispatchBindImageTexturesTest::iterate()
3917 {
3918 	static const GLchar* cs = "#version 440 core\n"
3919 							  "\n"
3920 							  "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
3921 							  "\n"
3922 							  "IMAGE_LIST\n"
3923 							  "layout (std140, binding = 0) buffer SSB {\n"
3924 							  "    uint sum;\n"
3925 							  "} ssb;\n"
3926 							  "\n"
3927 							  "void main()\n"
3928 							  "{\n"
3929 							  "    uvec4 sum = SUM_LIST;\n"
3930 							  "    ssb.sum = sum.r\n;"
3931 							  "}\n"
3932 							  "\n";
3933 
3934 	static const GLchar* image = "layout (location = XXX, r32ui) readonly uniform IMAGE iXXX;";
3935 
3936 	static const GLchar* loading[] = {
3937 		"imageLoad(iXXX, COORDS)", "imageLoad(iXXX, COORDS)",	"imageLoad(iXXX, COORDS)",   "imageLoad(iXXX, COORDS)",
3938 		"imageLoad(iXXX, COORDS)", "imageLoad(iXXX, COORDS)",	"imageLoad(iXXX, COORDS)",   "imageLoad(iXXX, COORDS)",
3939 		"imageLoad(iXXX, COORDS)", "imageLoad(iXXX, COORDS, 0)", "imageLoad(iXXX, COORDS, 0)"
3940 	};
3941 
3942 	static const GLchar* images[] = { "uimage1D",	 "uimage1DArray", "uimage2D",		 "uimage2DArray",
3943 									  "uimage3D",	 "uimageBuffer",  "uimageCube",	 "uimageCubeArray",
3944 									  "uimage2DRect", "uimage2DMS",	"uimage2DMSArray" };
3945 
3946 	static const GLchar* coordinates[] = {
3947 		"0",
3948 		"ivec2(0, 0)",
3949 		"ivec2(0, 0)",
3950 		"ivec3(0, 0, 0)",
3951 		"ivec3(0, 0, 0)",
3952 		"0",
3953 		"ivec3(0, 0, 0)",
3954 		"ivec3(0, 0, 0)",
3955 		"ivec2(0, 0)",
3956 		"ivec2(0, 0)",
3957 		"ivec3(0, 0, 0)",
3958 	};
3959 
3960 	static const GLuint depth  = 6;
3961 	static const GLuint height = 6;
3962 	static const GLuint width  = 6;
3963 
3964 	const Functions& gl = m_context.getRenderContext().getFunctions();
3965 
3966 	bool test_result = true;
3967 
3968 #if DEBUG_ENBALE_MESSAGE_CALLBACK
3969 	gl.debugMessageCallback(debug_proc, &m_context);
3970 	GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
3971 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
3972 
3973 	GLint  max_textures		 = 0;
3974 	GLint  max_image_samples = 0;
3975 	GLuint sum				 = 0;
3976 
3977 	/* Get max */
3978 	gl.getIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &max_textures);
3979 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3980 
3981 	/* Check if load/store from multisampled images is supported */
3982 	gl.getIntegerv(GL_MAX_IMAGE_SAMPLES, &max_image_samples);
3983 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3984 
3985 	/* Textures */
3986 	/* Storage */
3987 	std::vector<Texture> texture;
3988 	std::vector<GLuint>  texture_ids;
3989 	Buffer				 texture_buffer;
3990 
3991 	texture.resize(max_textures);
3992 	texture_ids.resize(max_textures);
3993 
3994 	/* Prepare */
3995 	for (GLint i = 0; i < max_textures; ++i)
3996 	{
3997 		GLenum target = getTarget(i);
3998 		if (target >= GL_TEXTURE_2D_MULTISAMPLE && max_image_samples == 0)
3999 			target = GL_TEXTURE_2D;
4000 
4001 		GLuint data[width * height * depth];
4002 
4003 		for (GLuint j = 0; j < width * height * depth; ++j)
4004 		{
4005 			data[j] = i;
4006 		}
4007 
4008 		sum += i;
4009 
4010 		bool is_array = false;
4011 
4012 		switch (target)
4013 		{
4014 		case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
4015 			is_array = true;
4016 		/* Intentional fallthrough */
4017 
4018 		case GL_TEXTURE_2D_MULTISAMPLE:
4019 			texture[i].InitStorage(m_context, target, 1, GL_R32UI, width, height, depth);
4020 			fillMSTexture(m_context, texture[i].m_id, i, is_array);
4021 			break;
4022 
4023 		case GL_TEXTURE_BUFFER:
4024 			texture_buffer.InitData(m_context, GL_TEXTURE_BUFFER, GL_DYNAMIC_COPY, sizeof(data), data);
4025 			texture[i].InitBuffer(m_context, GL_R32UI, texture_buffer.m_id);
4026 			break;
4027 
4028 		default:
4029 			texture[i].InitStorage(m_context, target, 1, GL_R32UI, width, height, depth);
4030 			Texture::Bind(gl, texture[i].m_id, target);
4031 			Texture::SubImage(gl, target, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height, depth,
4032 							  GL_RED_INTEGER, GL_UNSIGNED_INT, &data);
4033 			break;
4034 		}
4035 
4036 		/* Clean */
4037 		Texture::Bind(gl, 0, target);
4038 
4039 		texture_ids[i] = texture[i].m_id;
4040 	}
4041 
4042 	gl.bindImageTextures(0 /* first */, max_textures /* count */, &texture_ids[0]);
4043 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTextures");
4044 
4045 	/* SSBO */
4046 	Buffer ssb_buffer;
4047 	ssb_buffer.InitData(m_context, GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, sizeof(GLuint), 0 /* data */);
4048 
4049 	ssb_buffer.BindBase(0);
4050 
4051 	/* Prepare program */
4052 	size_t		load_position	= 0;
4053 	size_t		sum_position	 = 0;
4054 	std::string cs_source		 = cs;
4055 	GLint		max_target_index = (GLint)(max_image_samples > 0 ? s_n_texture_tragets : s_n_texture_tragets - 2);
4056 	for (GLint i = 0; i < max_textures; ++i)
4057 	{
4058 		size_t load_start_position = load_position;
4059 		size_t sum_start_position  = sum_position;
4060 
4061 		GLchar index[16];
4062 
4063 		sprintf(index, "%d", i);
4064 
4065 		const GLchar* coords	   = 0;
4066 		const GLchar* image_type   = 0;
4067 		const GLchar* loading_code = 0;
4068 
4069 		if (i < max_target_index)
4070 		{
4071 			coords		 = coordinates[i];
4072 			image_type   = images[i];
4073 			loading_code = loading[i];
4074 		}
4075 		else
4076 		{
4077 			coords		 = coordinates[2]; /* vec2(0.5f, 0.5f) */
4078 			image_type   = images[2];	  /* usampler2D */
4079 			loading_code = loading[2];	 /* texture(sXXX, COORDS) */
4080 		}
4081 
4082 		/* Add entry to ubo list */
4083 		replaceToken("IMAGE_LIST", load_position, "IMAGE\nIMAGE_LIST", cs_source);
4084 		load_position = load_start_position;
4085 
4086 		replaceToken("IMAGE", load_position, image, cs_source);
4087 		load_position = load_start_position;
4088 
4089 		replaceToken("XXX", load_position, index, cs_source);
4090 		replaceToken("IMAGE", load_position, image_type, cs_source);
4091 		replaceToken("XXX", load_position, index, cs_source);
4092 
4093 		/* Add entry to sum list */
4094 		replaceToken("SUM_LIST", sum_position, "LOADING + SUM_LIST", cs_source);
4095 		sum_position = sum_start_position;
4096 
4097 		replaceToken("LOADING", sum_position, loading_code, cs_source);
4098 		sum_position = sum_start_position;
4099 
4100 		replaceToken("XXX", sum_position, index, cs_source);
4101 		replaceToken("COORDS", sum_position, coords, cs_source);
4102 	}
4103 
4104 	/* Remove token for lists */
4105 	replaceToken(" + SUM_LIST", sum_position, "", cs_source);
4106 	replaceToken("IMAGE_LIST", load_position, "", cs_source);
4107 
4108 	Program program(m_context);
4109 	program.Init(cs_source.c_str(), "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
4110 
4111 	program.Use();
4112 
4113 	/* Set images */
4114 	for (GLint i = 0; i < max_textures; ++i)
4115 	{
4116 		gl.uniform1i(i, i);
4117 		GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
4118 	}
4119 
4120 	gl.dispatchCompute(1, 1, 1);
4121 	GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
4122 
4123 	gl.memoryBarrier(GL_ALL_BARRIER_BITS);
4124 	GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
4125 
4126 	GLuint* result = (GLuint*)gl.mapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY);
4127 	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
4128 
4129 	if (0 != memcmp(result, &sum, sizeof(sum)))
4130 	{
4131 		test_result = false;
4132 	}
4133 
4134 	gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
4135 	gl.getError(); /* Ignore error */
4136 
4137 	/* Set result */
4138 	if (true == test_result)
4139 	{
4140 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
4141 	}
4142 	else
4143 	{
4144 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4145 	}
4146 
4147 	/* Done */
4148 	return tcu::TestNode::STOP;
4149 }
4150 
4151 /** Constructor
4152  *
4153  * @param context Test context
4154  **/
DispatchBindSamplersTest(deqp::Context & context)4155 DispatchBindSamplersTest::DispatchBindSamplersTest(deqp::Context& context)
4156 	: TestCase(context, "dispatch_bind_samplers", "Tests BindSamplers with dispatch command")
4157 {
4158 	/* Nothing to be done */
4159 }
4160 
4161 /** Execute test
4162  *
4163  * @return tcu::TestNode::STOP
4164  **/
iterate()4165 tcu::TestNode::IterateResult DispatchBindSamplersTest::iterate()
4166 {
4167 	static const GLchar* cs = "#version 440 core\n"
4168 							  "\n"
4169 							  "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
4170 							  "\n"
4171 							  "SAMPLER_LIST\n"
4172 							  "layout (std140, binding = 0) buffer SSB {\n"
4173 							  "    uint sum;\n"
4174 							  "} ssb;\n"
4175 							  "\n"
4176 							  "void main()\n"
4177 							  "{\n"
4178 							  "    uvec4 sum = SUM_LIST;\n"
4179 							  "    ssb.sum = sum.r\n;"
4180 							  "}\n"
4181 							  "\n";
4182 
4183 	static const GLchar* sampler = "layout (location = XXX) uniform usampler2D sXXX;";
4184 
4185 	static const GLchar* sampling = "texture(sXXX, vec2(1.5f, 0.5f))";
4186 
4187 	static const GLuint depth  = 1;
4188 	static const GLuint height = 8;
4189 	static const GLuint width  = 8;
4190 
4191 	const Functions& gl = m_context.getRenderContext().getFunctions();
4192 
4193 	bool test_result = true;
4194 
4195 #if DEBUG_ENBALE_MESSAGE_CALLBACK
4196 	gl.debugMessageCallback(debug_proc, &m_context);
4197 	GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
4198 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
4199 
4200 	GLint max_textures = 0;
4201 
4202 	/* Get max */
4203 	gl.getIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &max_textures);
4204 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
4205 
4206 	/* Textures */
4207 	/* Storage */
4208 	std::vector<GLuint>  sampler_ids;
4209 	std::vector<Texture> texture;
4210 	std::vector<GLuint>  texture_ids;
4211 
4212 	sampler_ids.resize(max_textures);
4213 	texture.resize(max_textures);
4214 	texture_ids.resize(max_textures);
4215 
4216 	GLuint data[width * height * depth];
4217 
4218 	for (GLuint j = 0; j < width * height; ++j)
4219 	{
4220 		data[j] = 0;
4221 	}
4222 
4223 	{
4224 		const size_t last_line_offset		   = (height - 1) * width;
4225 		const size_t last_pixel_in_line_offset = width - 1;
4226 
4227 		for (GLuint j = 0; j < width; ++j)
4228 		{
4229 			data[j]					   = 1;
4230 			data[j + last_line_offset] = 1;
4231 		}
4232 
4233 		for (GLuint j = 0; j < height; ++j)
4234 		{
4235 			const size_t line_offset = j * width;
4236 
4237 			data[line_offset]							  = 1;
4238 			data[line_offset + last_pixel_in_line_offset] = 1;
4239 		}
4240 	}
4241 
4242 	/* Prepare */
4243 	for (GLint i = 0; i < max_textures; ++i)
4244 	{
4245 		texture[i].InitStorage(m_context, GL_TEXTURE_2D, 1, GL_R32UI, width, height, depth);
4246 		Texture::Bind(gl, texture[i].m_id, GL_TEXTURE_2D);
4247 		Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height, depth,
4248 						  GL_RED_INTEGER, GL_UNSIGNED_INT, &data);
4249 
4250 		texture_ids[i] = texture[i].m_id;
4251 	}
4252 
4253 	/* Clean */
4254 	Texture::Bind(gl, 0, GL_TEXTURE_2D);
4255 
4256 	/* Execute the test */
4257 	gl.bindTextures(0 /* first */, max_textures /* count */, &texture_ids[0]);
4258 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindTextures");
4259 
4260 	/* SSBO */
4261 	Buffer ssb_buffer;
4262 	ssb_buffer.InitData(m_context, GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, sizeof(GLuint), 0 /* data */);
4263 
4264 	ssb_buffer.BindBase(0);
4265 
4266 	/* Prepare program */
4267 	size_t		sam_position = 0;
4268 	size_t		sum_position = 0;
4269 	std::string cs_source	= cs;
4270 
4271 	for (GLint i = 0; i < max_textures; ++i)
4272 	{
4273 		size_t sam_start_position = sam_position;
4274 		size_t sum_start_position = sum_position;
4275 
4276 		GLchar index[16];
4277 
4278 		sprintf(index, "%d", i);
4279 
4280 		/* Add entry to ubo list */
4281 		replaceToken("SAMPLER_LIST", sam_position, "SAMPLER\nSAMPLER_LIST", cs_source);
4282 		sam_position = sam_start_position;
4283 
4284 		replaceToken("SAMPLER", sam_position, sampler, cs_source);
4285 		sam_position = sam_start_position;
4286 
4287 		replaceToken("XXX", sam_position, index, cs_source);
4288 		replaceToken("XXX", sam_position, index, cs_source);
4289 
4290 		/* Add entry to sum list */
4291 		replaceToken("SUM_LIST", sum_position, "SAMPLING + SUM_LIST", cs_source);
4292 		sum_position = sum_start_position;
4293 
4294 		replaceToken("SAMPLING", sum_position, sampling, cs_source);
4295 		sum_position = sum_start_position;
4296 
4297 		replaceToken("XXX", sum_position, index, cs_source);
4298 	}
4299 
4300 	/* Remove token for lists */
4301 	replaceToken(" + SUM_LIST", sum_position, "", cs_source);
4302 	replaceToken("SAMPLER_LIST", sam_position, "", cs_source);
4303 
4304 	Program program(m_context);
4305 	program.Init(cs_source.c_str(), "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
4306 
4307 	program.Use();
4308 
4309 	/* Set texture units */
4310 	for (GLint i = 0; i < max_textures; ++i)
4311 	{
4312 		gl.uniform1i(i, i);
4313 		GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
4314 	}
4315 
4316 	/* Prepare samplers */
4317 	gl.genSamplers(max_textures, &sampler_ids[0]);
4318 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenSamplers");
4319 
4320 	try
4321 	{
4322 		gl.bindSamplers(0 /* first */, max_textures /* count */, &sampler_ids[0]);
4323 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindSamplers");
4324 
4325 		for (GLint i = 0; i < max_textures; ++i)
4326 		{
4327 			gl.samplerParameteri(sampler_ids[i], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
4328 			gl.samplerParameteri(sampler_ids[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4329 			gl.samplerParameteri(sampler_ids[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4330 			GLU_EXPECT_NO_ERROR(gl.getError(), "SamplerParameteri");
4331 		}
4332 
4333 		gl.dispatchCompute(1, 1, 1);
4334 		GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
4335 
4336 		gl.memoryBarrier(GL_ALL_BARRIER_BITS);
4337 		GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
4338 	}
4339 	catch (const std::exception&)
4340 	{
4341 		gl.deleteSamplers(max_textures, &sampler_ids[0]);
4342 
4343 		TCU_FAIL("Unexpected error generated");
4344 	}
4345 
4346 	/* Remove samplers */
4347 	gl.deleteSamplers(max_textures, &sampler_ids[0]);
4348 
4349 	/* Verify results */
4350 	GLuint* result = (GLuint*)gl.mapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY);
4351 	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
4352 
4353 	if (0 != memcmp(result, &max_textures, sizeof(max_textures)))
4354 	{
4355 		test_result = false;
4356 	}
4357 
4358 	gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
4359 	gl.getError(); /* Ignore error */
4360 
4361 	/* Set result */
4362 	if (true == test_result)
4363 	{
4364 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
4365 	}
4366 	else
4367 	{
4368 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4369 	}
4370 
4371 	/* Done */
4372 	return tcu::TestNode::STOP;
4373 }
4374 
4375 /** Constructor
4376  *
4377  * @param context Test context
4378  **/
DrawBindVertexBuffersTest(deqp::Context & context)4379 DrawBindVertexBuffersTest::DrawBindVertexBuffersTest(deqp::Context& context)
4380 	: TestCase(context, "draw_bind_vertex_buffers", "Tests BindVertexBuffers command with drawArrays")
4381 {
4382 	/* Nothing to be done */
4383 }
4384 
4385 /** Execute test
4386  *
4387  * @return tcu::TestNode::STOP
4388  **/
iterate()4389 tcu::TestNode::IterateResult DrawBindVertexBuffersTest::iterate()
4390 {
4391 	static const GLchar* vs = "#version 440 core\n"
4392 							  "\n"
4393 							  "ATTRIBUTE_LIST\n"
4394 							  "\n"
4395 							  "out vec4 vs_gs_sum;\n"
4396 							  "\n"
4397 							  "void main()\n"
4398 							  "{\n"
4399 							  "    vs_gs_sum = SUM_LIST;\n"
4400 							  "}\n"
4401 							  "\n";
4402 
4403 	static const GLchar* gs = "#version 440 core\n"
4404 							  "\n"
4405 							  "layout(points)                           in;\n"
4406 							  "layout(triangle_strip, max_vertices = 4) out;\n"
4407 							  "\n"
4408 							  "in  vec4 vs_gs_sum[];\n"
4409 							  "out vec4 gs_fs_sum;\n"
4410 							  "\n"
4411 							  "void main()\n"
4412 							  "{\n"
4413 							  "    gs_fs_sum   = vs_gs_sum[0];\n"
4414 							  "    gl_Position = vec4(-1, -1, 0, 1);\n"
4415 							  "    EmitVertex();\n"
4416 							  "    gs_fs_sum   = vs_gs_sum[0];\n"
4417 							  "    gl_Position = vec4(-1, 1, 0, 1);\n"
4418 							  "    EmitVertex();\n"
4419 							  "    gs_fs_sum   = vs_gs_sum[0];\n"
4420 							  "    gl_Position = vec4(1, -1, 0, 1);\n"
4421 							  "    EmitVertex();\n"
4422 							  "    gs_fs_sum   = vs_gs_sum[0];\n"
4423 							  "    gl_Position = vec4(1, 1, 0, 1);\n"
4424 							  "    EmitVertex();\n"
4425 							  "}\n"
4426 							  "\n";
4427 
4428 	static const GLchar* fs = "#version 440 core\n"
4429 							  "\n"
4430 							  "in  vec4 gs_fs_sum;\n"
4431 							  "out vec4 fs_out;\n"
4432 							  "\n"
4433 							  "void main()\n"
4434 							  "{\n"
4435 							  "    fs_out = gs_fs_sum;\n"
4436 							  "}\n"
4437 							  "\n";
4438 
4439 	static const GLchar* attribute = "layout (location = XXX) in vec4 aXXX;";
4440 
4441 	static const GLuint height = 8;
4442 	static const GLuint width  = 8;
4443 
4444 	const Functions& gl = m_context.getRenderContext().getFunctions();
4445 
4446 	bool test_result = true;
4447 
4448 #if DEBUG_ENBALE_MESSAGE_CALLBACK
4449 	gl.debugMessageCallback(debug_proc, &m_context);
4450 	GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
4451 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
4452 
4453 	static const GLintptr attribute_size = 4 * sizeof(GLfloat);
4454 
4455 	GLint  max_buffers = 0;
4456 	GLuint vao		   = 0;
4457 
4458 	/* Get max */
4459 	gl.getIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &max_buffers);
4460 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
4461 
4462 	/* Storage */
4463 	Buffer				  buffer;
4464 	std::vector<GLuint>   buffer_ids;
4465 	std::vector<GLfloat>  data;
4466 	std::vector<GLintptr> offsets;
4467 	std::vector<GLsizei>  strides;
4468 
4469 	buffer_ids.resize(max_buffers);
4470 	data.resize(max_buffers * 4);
4471 	offsets.resize(max_buffers);
4472 	strides.resize(max_buffers);
4473 
4474 	/* Prepare data */
4475 	const GLfloat value = 1.0f / (GLfloat)max_buffers;
4476 
4477 	for (GLint i = 0; i < max_buffers; ++i)
4478 	{
4479 		data[i * 4 + 0] = value;
4480 		data[i * 4 + 1] = value;
4481 		data[i * 4 + 2] = value;
4482 		data[i * 4 + 3] = value;
4483 	}
4484 
4485 	/* Prepare buffer */
4486 	buffer.InitData(m_context, GL_ARRAY_BUFFER, GL_DYNAMIC_COPY, data.size() * sizeof(GLfloat), &data[0]);
4487 
4488 	for (GLint i = 0; i < max_buffers; ++i)
4489 	{
4490 		buffer_ids[i] = buffer.m_id;
4491 		offsets[i]	= i * attribute_size;
4492 		strides[i]	= attribute_size;
4493 	}
4494 
4495 	/* Prepare FBO */
4496 	Framebuffer framebuffer(m_context);
4497 	Texture		texture;
4498 
4499 	texture.InitStorage(m_context, GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, width, height, 1 /* depth */);
4500 
4501 	/* */
4502 	Framebuffer::Generate(gl, framebuffer.m_id);
4503 	Framebuffer::Bind(gl, GL_DRAW_FRAMEBUFFER, framebuffer.m_id);
4504 	Framebuffer::AttachTexture(gl, GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.m_id, 0 /* level */, width,
4505 							   height);
4506 
4507 	/* Prepare program */
4508 	size_t		attr_position = 0;
4509 	size_t		sum_position  = 0;
4510 	std::string vs_source	 = vs;
4511 	for (GLint i = 0; i < max_buffers; ++i)
4512 	{
4513 		size_t attr_start_position = attr_position;
4514 		size_t sum_start_position  = sum_position;
4515 
4516 		GLchar index[16];
4517 
4518 		sprintf(index, "%d", i);
4519 
4520 		/* Add entry to ubo list */
4521 		replaceToken("ATTRIBUTE_LIST", attr_position, "ATTRIBUTE\nATTRIBUTE_LIST", vs_source);
4522 		attr_position = attr_start_position;
4523 
4524 		replaceToken("ATTRIBUTE", attr_position, attribute, vs_source);
4525 		attr_position = attr_start_position;
4526 
4527 		replaceToken("XXX", attr_position, index, vs_source);
4528 		replaceToken("XXX", attr_position, index, vs_source);
4529 
4530 		/* Add entry to sum list */
4531 		replaceToken("SUM_LIST", sum_position, "aXXX + SUM_LIST", vs_source);
4532 		sum_position = sum_start_position;
4533 
4534 		replaceToken("XXX", sum_position, index, vs_source);
4535 	}
4536 
4537 	/* Remove token for lists */
4538 	replaceToken(" + SUM_LIST", sum_position, "", vs_source);
4539 	replaceToken("ATTRIBUTE_LIST", attr_position, "", vs_source);
4540 
4541 	Program program(m_context);
4542 	program.Init("" /* cs */, fs, gs, "" /* tcs */, "" /* tes */, vs_source.c_str());
4543 
4544 	program.Use();
4545 
4546 	gl.genVertexArrays(1, &vao);
4547 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
4548 
4549 	try
4550 	{
4551 		gl.bindVertexArray(vao);
4552 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArrays");
4553 
4554 		for (GLint i = 0; i < max_buffers; ++i)
4555 		{
4556 			gl.enableVertexAttribArray(i);
4557 			GLU_EXPECT_NO_ERROR(gl.getError(), "EnableVertexAttribArray");
4558 		}
4559 
4560 		/* */
4561 		gl.bindVertexBuffers(0, max_buffers, &buffer_ids[0], &offsets[0], &strides[0]);
4562 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexBuffers");
4563 
4564 		/* */
4565 		gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
4566 		GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
4567 
4568 		for (GLint i = 0; i < max_buffers; ++i)
4569 		{
4570 			gl.disableVertexAttribArray(i);
4571 			GLU_EXPECT_NO_ERROR(gl.getError(), "DisableVertexAttribArray");
4572 		}
4573 	}
4574 	catch (const std::exception&)
4575 	{
4576 		gl.deleteVertexArrays(1, &vao);
4577 
4578 		TCU_FAIL("Unexpected error generated");
4579 	}
4580 
4581 	gl.deleteVertexArrays(1, &vao);
4582 	GLU_EXPECT_NO_ERROR(gl.getError(), "DeleteVertexArrays");
4583 
4584 	/* Verify results */
4585 	GLuint pixels[width * height];
4586 	for (GLuint i = 0; i < width * height; ++i)
4587 	{
4588 		pixels[i] = 0;
4589 	}
4590 
4591 	Texture::Bind(gl, texture.m_id, GL_TEXTURE_2D);
4592 
4593 	Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
4594 
4595 	/* Unbind */
4596 	Texture::Bind(gl, 0, GL_TEXTURE_2D);
4597 
4598 	/* Verify */
4599 	for (GLuint i = 0; i < width * height; ++i)
4600 	{
4601 		if (0xffffffff != pixels[i])
4602 		{
4603 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << (GLuint)pixels[i]
4604 												<< " at offset: " << i << tcu::TestLog::EndMessage;
4605 
4606 			test_result = false;
4607 
4608 			break;
4609 		}
4610 	}
4611 
4612 	/* Set result */
4613 	if (true == test_result)
4614 	{
4615 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
4616 	}
4617 	else
4618 	{
4619 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4620 	}
4621 
4622 	/* Done */
4623 	return tcu::TestNode::STOP;
4624 }
4625 } /* MultiBind */
4626 
4627 /** Constructor.
4628  *
4629  *  @param context Rendering context.
4630  **/
MultiBindTests(deqp::Context & context)4631 MultiBindTests::MultiBindTests(deqp::Context& context)
4632 	: TestCaseGroup(context, "multi_bind", "Verifies \"multi bind\" functionality")
4633 {
4634 	/* Left blank on purpose */
4635 }
4636 
4637 /** Initializes a multi_bind test group.
4638  *
4639  **/
init(void)4640 void MultiBindTests::init(void)
4641 {
4642 	addChild(new MultiBind::DispatchBindTexturesTest(m_context));
4643 
4644 	addChild(new MultiBind::ErrorsBindBuffersTest(m_context));
4645 	addChild(new MultiBind::ErrorsBindTexturesTest(m_context));
4646 	addChild(new MultiBind::ErrorsBindSamplersTest(m_context));
4647 	addChild(new MultiBind::ErrorsBindImageTexturesTest(m_context));
4648 	addChild(new MultiBind::ErrorsBindVertexBuffersTest(m_context));
4649 	addChild(new MultiBind::FunctionalBindBuffersBaseTest(m_context));
4650 	addChild(new MultiBind::FunctionalBindBuffersRangeTest(m_context));
4651 	addChild(new MultiBind::FunctionalBindTexturesTest(m_context));
4652 	addChild(new MultiBind::FunctionalBindSamplersTest(m_context));
4653 	addChild(new MultiBind::FunctionalBindImageTexturesTest(m_context));
4654 	addChild(new MultiBind::FunctionalBindVertexBuffersTest(m_context));
4655 	addChild(new MultiBind::DispatchBindBuffersBaseTest(m_context));
4656 	addChild(new MultiBind::DispatchBindBuffersRangeTest(m_context));
4657 
4658 	addChild(new MultiBind::DispatchBindImageTexturesTest(m_context));
4659 	addChild(new MultiBind::DispatchBindSamplersTest(m_context));
4660 	addChild(new MultiBind::DrawBindVertexBuffersTest(m_context));
4661 }
4662 
4663 } /* gl4cts namespace */
4664