• 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 		break;
1099 	}
1100 }
1101 
1102 /** Generate texture instance
1103  *
1104  * @param gl     GL functions
1105  * @param out_id Id of texture
1106  **/
Generate(const glw::Functions & gl,glw::GLuint & out_id)1107 void Texture::Generate(const glw::Functions& gl, glw::GLuint& out_id)
1108 {
1109 	GLuint id = m_invalid_id;
1110 
1111 	gl.genTextures(1, &id);
1112 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
1113 
1114 	if (m_invalid_id == id)
1115 	{
1116 		TCU_FAIL("Invalid id");
1117 	}
1118 
1119 	out_id = id;
1120 }
1121 
1122 /** Get texture data
1123  *
1124  * @param gl       GL functions
1125  * @param target   Texture target
1126  * @param format   Format of data
1127  * @param type     Type of data
1128  * @param out_data Buffer for data
1129  **/
GetData(const glw::Functions & gl,glw::GLint level,glw::GLenum target,glw::GLenum format,glw::GLenum type,glw::GLvoid * out_data)1130 void Texture::GetData(const glw::Functions& gl, glw::GLint level, glw::GLenum target, glw::GLenum format,
1131 					  glw::GLenum type, glw::GLvoid* out_data)
1132 {
1133 	gl.getTexImage(target, level, format, type, out_data);
1134 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
1135 }
1136 
1137 /** Generate texture instance
1138  *
1139  * @param gl     GL functions
1140  * @param target Texture target
1141  * @param level  Mipmap level
1142  * @param pname  Parameter to query
1143  * @param param  Result of query
1144  **/
GetLevelParameter(const glw::Functions & gl,glw::GLenum target,glw::GLint level,glw::GLenum pname,glw::GLint * param)1145 void Texture::GetLevelParameter(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLenum pname,
1146 								glw::GLint* param)
1147 {
1148 	gl.getTexLevelParameteriv(target, level, pname, param);
1149 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexLevelParameteriv");
1150 }
1151 
1152 /** Set contents of texture
1153  *
1154  * @param gl              GL functions
1155  * @param target          Texture target
1156  * @param level           Mipmap level
1157  * @param internal_format Format of data
1158  * @param width           Width of texture
1159  * @param height          Height of texture
1160  * @param depth           Depth of texture
1161  * @param format          Format of data
1162  * @param type            Type of data
1163  * @param data            Buffer with image data
1164  **/
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)1165 void Texture::Image(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLenum internal_format,
1166 					glw::GLuint width, glw::GLuint height, glw::GLuint depth, glw::GLenum format, glw::GLenum type,
1167 					const glw::GLvoid* data)
1168 {
1169 	switch (target)
1170 	{
1171 	case GL_TEXTURE_1D:
1172 		gl.texImage1D(target, level, internal_format, width, 0 /* border */, format, type, data);
1173 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage1D");
1174 		break;
1175 	case GL_TEXTURE_1D_ARRAY:
1176 	case GL_TEXTURE_2D:
1177 	case GL_TEXTURE_RECTANGLE:
1178 		gl.texImage2D(target, level, internal_format, width, height, 0 /* border */, format, type, data);
1179 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage2D");
1180 		break;
1181 	case GL_TEXTURE_CUBE_MAP:
1182 		gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, internal_format, width, height, 0 /* border */, format,
1183 					  type, data);
1184 		gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, internal_format, width, height, 0 /* border */, format,
1185 					  type, data);
1186 		gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, internal_format, width, height, 0 /* border */, format,
1187 					  type, data);
1188 		gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, internal_format, width, height, 0 /* border */, format,
1189 					  type, data);
1190 		gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, internal_format, width, height, 0 /* border */, format,
1191 					  type, data);
1192 		gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, internal_format, width, height, 0 /* border */, format,
1193 					  type, data);
1194 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage2D");
1195 		break;
1196 	case GL_TEXTURE_3D:
1197 	case GL_TEXTURE_2D_ARRAY:
1198 		gl.texImage3D(target, level, internal_format, width, height, depth, 0 /* border */, format, type, data);
1199 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage3D");
1200 		break;
1201 	default:
1202 		TCU_FAIL("Invliad enum");
1203 		break;
1204 	}
1205 }
1206 
1207 /** Allocate storage for texture
1208  *
1209  * @param gl              GL functions
1210  * @param target          Texture target
1211  * @param levels          Number of levels
1212  * @param internal_format Internal format of texture
1213  * @param width           Width of texture
1214  * @param height          Height of texture
1215  * @param depth           Depth of texture
1216  **/
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)1217 void Texture::Storage(const glw::Functions& gl, glw::GLenum target, glw::GLsizei levels, glw::GLenum internal_format,
1218 					  glw::GLuint width, glw::GLuint height, glw::GLuint depth, bool allow_error)
1219 {
1220 	switch (target)
1221 	{
1222 	case GL_TEXTURE_1D:
1223 		gl.texStorage1D(target, levels, internal_format, width);
1224 		if (!allow_error)
1225 		{
1226 			GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage1D");
1227 		}
1228 		break;
1229 	case GL_TEXTURE_1D_ARRAY:
1230 	case GL_TEXTURE_2D:
1231 	case GL_TEXTURE_RECTANGLE:
1232 	case GL_TEXTURE_CUBE_MAP:
1233 		gl.texStorage2D(target, levels, internal_format, width, height);
1234 		if (!allow_error)
1235 		{
1236 			GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
1237 		}
1238 		break;
1239 	case GL_TEXTURE_2D_MULTISAMPLE:
1240 		gl.texStorage2DMultisample(target, levels, internal_format, width, height, GL_FALSE);
1241 		if (!allow_error)
1242 		{
1243 			GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2DMultisample");
1244 		}
1245 		break;
1246 	case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1247 		gl.texStorage3DMultisample(target, levels, internal_format, width, height, depth, GL_FALSE);
1248 		if (!allow_error)
1249 		{
1250 			GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage3DMultisample");
1251 		}
1252 		break;
1253 	case GL_TEXTURE_3D:
1254 	case GL_TEXTURE_2D_ARRAY:
1255 	case GL_TEXTURE_CUBE_MAP_ARRAY:
1256 		gl.texStorage3D(target, levels, internal_format, width, height, depth);
1257 		if (!allow_error)
1258 		{
1259 			GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage3D");
1260 		}
1261 		break;
1262 	default:
1263 		TCU_FAIL("Invliad enum");
1264 		break;
1265 	}
1266 }
1267 
1268 /** Set contents of texture
1269  *
1270  * @param gl              GL functions
1271  * @param target          Texture target
1272  * @param level           Mipmap level
1273  * @param x               X offset
1274  * @param y               Y offset
1275  * @param z               Z offset
1276  * @param width           Width of texture
1277  * @param height          Height of texture
1278  * @param depth           Depth of texture
1279  * @param format          Format of data
1280  * @param type            Type of data
1281  * @param pixels          Buffer with image data
1282  **/
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)1283 void Texture::SubImage(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLint x, glw::GLint y,
1284 					   glw::GLint z, glw::GLsizei width, glw::GLsizei height, glw::GLsizei depth, glw::GLenum format,
1285 					   glw::GLenum type, const glw::GLvoid* pixels)
1286 {
1287 	switch (target)
1288 	{
1289 	case GL_TEXTURE_1D:
1290 		gl.texSubImage1D(target, level, x, width, format, type, pixels);
1291 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage1D");
1292 		break;
1293 	case GL_TEXTURE_1D_ARRAY:
1294 	case GL_TEXTURE_2D:
1295 	case GL_TEXTURE_RECTANGLE:
1296 		gl.texSubImage2D(target, level, x, y, width, height, format, type, pixels);
1297 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
1298 		break;
1299 	case GL_TEXTURE_CUBE_MAP:
1300 		gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, x, y, width, height, format, type, pixels);
1301 		gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, x, y, width, height, format, type, pixels);
1302 		gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, x, y, width, height, format, type, pixels);
1303 		gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, x, y, width, height, format, type, pixels);
1304 		gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, x, y, width, height, format, type, pixels);
1305 		gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, x, y, width, height, format, type, pixels);
1306 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
1307 		break;
1308 	case GL_TEXTURE_3D:
1309 	case GL_TEXTURE_2D_ARRAY:
1310 	case GL_TEXTURE_CUBE_MAP_ARRAY:
1311 		gl.texSubImage3D(target, level, x, y, z, width, height, depth, format, type, pixels);
1312 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage3D");
1313 		break;
1314 	default:
1315 		TCU_FAIL("Invliad enum");
1316 		break;
1317 	}
1318 }
1319 
1320 /* Gather info about buffer target */
1321 struct bufferTargetInfo
1322 {
1323 	GLenum m_target;
1324 	GLenum m_pname_alignment;
1325 	GLenum m_pname_binding;
1326 	GLenum m_pname_max;
1327 	GLenum m_pname_max_size;
1328 };
1329 
1330 /* Gather info about texture target */
1331 struct textureTargetInfo
1332 {
1333 	GLenum		  m_target;
1334 	GLenum		  m_pname_binding;
1335 	const GLchar* m_name;
1336 };
1337 
1338 /* Collects information about buffers */
1339 static const bufferTargetInfo s_buffer_infos[] = {
1340 	{ GL_ATOMIC_COUNTER_BUFFER, 0, GL_ATOMIC_COUNTER_BUFFER_BINDING, GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS,
1341 	  GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE },
1342 	{
1343 		GL_TRANSFORM_FEEDBACK_BUFFER, 0, GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, GL_MAX_TRANSFORM_FEEDBACK_BUFFERS,
1344 		GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,
1345 	},
1346 	{ GL_UNIFORM_BUFFER, GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, GL_UNIFORM_BUFFER_BINDING, GL_MAX_UNIFORM_BUFFER_BINDINGS,
1347 	  GL_MAX_UNIFORM_BLOCK_SIZE },
1348 	{ GL_SHADER_STORAGE_BUFFER, GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, GL_SHADER_STORAGE_BUFFER_BINDING,
1349 	  GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, GL_MAX_SHADER_STORAGE_BLOCK_SIZE },
1350 };
1351 
1352 static const size_t s_n_buffer_tragets = sizeof(s_buffer_infos) / sizeof(s_buffer_infos[0]);
1353 
1354 /* Collects information about textures */
1355 static const textureTargetInfo s_texture_infos[] = {
1356 	{ GL_TEXTURE_1D, GL_TEXTURE_BINDING_1D, "1D" },
1357 	{ GL_TEXTURE_1D_ARRAY, GL_TEXTURE_BINDING_1D_ARRAY, "1D_ARRAY" },
1358 	{ GL_TEXTURE_2D, GL_TEXTURE_BINDING_2D, "2D" },
1359 	{ GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BINDING_2D_ARRAY, "2D_ARRAY" },
1360 	{ GL_TEXTURE_3D, GL_TEXTURE_BINDING_3D, "3D" },
1361 	{ GL_TEXTURE_BUFFER, GL_TEXTURE_BINDING_BUFFER, "BUFFER" },
1362 	{ GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BINDING_CUBE_MAP, "CUBE" },
1363 	{ GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_BINDING_CUBE_MAP_ARRAY, "CUBE_ARRAY" },
1364 	{ GL_TEXTURE_RECTANGLE, GL_TEXTURE_BINDING_RECTANGLE, "RECTANGLE" },
1365 	{ GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_BINDING_2D_MULTISAMPLE, "2D_MS" },
1366 	{ GL_TEXTURE_2D_MULTISAMPLE_ARRAY, GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY, "2D_MS_ARRAY" }
1367 };
1368 
1369 static const size_t s_n_texture_tragets = sizeof(s_texture_infos) / sizeof(s_texture_infos[0]);
1370 
1371 /** Macro, verifies generated error, logs error message and throws failure
1372  *
1373  * @param expected_error Expected error value
1374  * @param error_message  Message logged if generated error is not the expected one
1375  **/
1376 #define CHECK_ERROR(expected_error, error_message)                                                      \
1377 	{                                                                                                   \
1378 		GLenum generated_error = gl.getError();                                                         \
1379                                                                                                         \
1380 		if (expected_error != generated_error)                                                          \
1381 		{                                                                                               \
1382 			m_context.getTestContext().getLog()                                                         \
1383 				<< tcu::TestLog::Message << "File: " << __FILE__ << ", line: " << __LINE__              \
1384 				<< ". Got wrong error: " << glu::getErrorStr(generated_error)                           \
1385 				<< ", expected: " << glu::getErrorStr(expected_error) << ", message: " << error_message \
1386 				<< tcu::TestLog::EndMessage;                                                            \
1387 			TCU_FAIL("Invalid error generated");                                                        \
1388 		}                                                                                               \
1389 	}
1390 
1391 /* Prototypes */
1392 void replaceToken(const GLchar* token, size_t& search_position, const GLchar* text, std::string& string);
1393 
1394 /** Checks binding
1395  *
1396  * @param context        Test contex
1397  * @param pname          Pname of binding
1398  * @param index          Index of binding
1399  * @param target_name    Name of target
1400  * @param expected_value Expected value of binding
1401  **/
checkBinding(deqp::Context & context,GLenum pname,GLuint index,const std::string & target_name,GLint expected_value)1402 void checkBinding(deqp::Context& context, GLenum pname, GLuint index, const std::string& target_name,
1403 				  GLint expected_value)
1404 {
1405 	const Functions& gl = context.getRenderContext().getFunctions();
1406 
1407 	GLint binding = -1;
1408 
1409 	gl.getIntegeri_v(pname, index, &binding);
1410 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegeri_v");
1411 
1412 	if (binding != expected_value)
1413 	{
1414 		context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid binding: " << binding
1415 										  << ", expected: " << expected_value << ". Target: " << target_name
1416 										  << " at index: " << index << tcu::TestLog::EndMessage;
1417 		TCU_FAIL("Invalid binding");
1418 	}
1419 }
1420 
1421 /** Checks bindings for given texture unit
1422  *
1423  * @param context        Test contex
1424  * @param pname          Binding pname of <expected_value>
1425  * @param index          Index of texture unit
1426  * @param expected_value Expected value of binding at <pname> target
1427  **/
checkTextureBinding(deqp::Context & context,GLenum pname,GLuint index,GLint expected_value)1428 void checkTextureBinding(deqp::Context& context, GLenum pname, GLuint index, GLint expected_value)
1429 {
1430 	const Functions& gl = context.getRenderContext().getFunctions();
1431 
1432 	for (size_t i = 0; i < s_n_texture_tragets; ++i)
1433 	{
1434 		const GLenum  pname_binding = s_texture_infos[i].m_pname_binding;
1435 		const GLchar* target_name   = s_texture_infos[i].m_name;
1436 
1437 		GLint binding = -1;
1438 		GLint value   = 0;
1439 
1440 		gl.getIntegeri_v(pname_binding, index, &binding);
1441 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegeri_v");
1442 
1443 		if (pname_binding == pname)
1444 		{
1445 			value = (GLint)expected_value;
1446 		}
1447 
1448 		if (binding != value)
1449 		{
1450 			context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid binding: " << binding
1451 											  << ", expected: " << expected_value << ". Target: " << target_name
1452 											  << " at index: " << index << tcu::TestLog::EndMessage;
1453 			TCU_FAIL("Invalid binding");
1454 		}
1455 	}
1456 }
1457 
1458 /** Checks binding
1459  *
1460  * @param context        Test context
1461  * @param index          Index of binding
1462  * @param expected_value Expected value of binding
1463  **/
checkVertexAttribBinding(deqp::Context & context,GLuint index,GLint expected_value)1464 void checkVertexAttribBinding(deqp::Context& context, GLuint index, GLint expected_value)
1465 {
1466 	const Functions& gl = context.getRenderContext().getFunctions();
1467 
1468 	GLint binding = -1;
1469 
1470 	gl.getVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &binding);
1471 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetVertexAttribiv");
1472 
1473 	if (binding != expected_value)
1474 	{
1475 		context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid binding: " << binding
1476 										  << ", expected: " << expected_value << ". Target: Vertex attribute"
1477 										  << " at index: " << index << tcu::TestLog::EndMessage;
1478 		TCU_FAIL("Invalid binding");
1479 	}
1480 }
1481 
1482 /** Fills MS texture with specified value
1483  *
1484  * @param context        Test context
1485  * @param texture_id     Index of binding
1486  * @param value          Value for texture
1487  * @param is_array       Selects if array target should be used
1488  **/
fillMSTexture(deqp::Context & context,GLuint texture_id,GLuint value,bool is_array)1489 void fillMSTexture(deqp::Context& context, GLuint texture_id, GLuint value, bool is_array)
1490 {
1491 	/* */
1492 	static const GLchar* cs = "#version 430 core\n"
1493 							  "\n"
1494 							  "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1495 							  "\n"
1496 							  "layout (location = 0) writeonly uniform IMAGE uni_image;\n"
1497 							  "\n"
1498 							  "layout (location = 1) uniform uint uni_value;\n"
1499 							  "\n"
1500 							  "void main()\n"
1501 							  "{\n"
1502 							  "    const POINT;\n"
1503 							  "\n"
1504 							  "    imageStore(uni_image, point, 0, uvec4(uni_value, 0, 0, 0));\n"
1505 							  "}\n"
1506 							  "\n";
1507 
1508 	static const GLchar* array_image   = "uimage2DMSArray";
1509 	static const GLchar* array_point   = "ivec3 point = ivec3(gl_WorkGroupID.x, gl_WorkGroupID.y, 0)";
1510 	static const GLchar* regular_image = "uimage2DMS";
1511 	static const GLchar* regular_point = "ivec2 point = ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y)";
1512 
1513 	/* */
1514 	const Functions& gl		  = context.getRenderContext().getFunctions();
1515 	const GLchar*	image	= (true == is_array) ? array_image : regular_image;
1516 	const GLchar*	point	= (true == is_array) ? array_point : regular_point;
1517 	size_t			 position = 0;
1518 	std::string		 source   = cs;
1519 
1520 	/* */
1521 	replaceToken("IMAGE", position, image, source);
1522 	replaceToken("POINT", position, point, source);
1523 
1524 	/* */
1525 	Program program(context);
1526 	program.Init(source.c_str(), "", "", "", "", "");
1527 	program.Use();
1528 
1529 	/* */
1530 	if (true == is_array)
1531 	{
1532 		gl.bindImageTexture(0 /* unit */, texture_id, 0 /* level */, GL_TRUE /* layered */, 0 /* layer */,
1533 							GL_WRITE_ONLY, GL_R32UI);
1534 	}
1535 	else
1536 	{
1537 		gl.bindImageTexture(0 /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
1538 							GL_WRITE_ONLY, GL_R32UI);
1539 	}
1540 
1541 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
1542 
1543 	gl.uniform1i(0 /* location */, 0 /* image unit*/);
1544 	GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
1545 
1546 	gl.uniform1ui(1 /* location */, value /* uni_value */);
1547 	GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1ui");
1548 
1549 	/* */
1550 	gl.dispatchCompute(6, 6, 1);
1551 	GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
1552 }
1553 
1554 /** Get texture binding pname for given index
1555  *
1556  * @param index Index of texture target
1557  *
1558  * @return Pname
1559  **/
getBinding(GLuint index)1560 GLenum getBinding(GLuint index)
1561 {
1562 	if (index < s_n_texture_tragets)
1563 	{
1564 		return s_texture_infos[index].m_pname_binding;
1565 	}
1566 	else
1567 	{
1568 		return GL_TEXTURE_BINDING_2D;
1569 	}
1570 }
1571 
1572 /** Get texture target for given index
1573  *
1574  * @param index Index of texture target
1575  *
1576  * @return Target
1577  **/
getTarget(GLuint index)1578 GLenum getTarget(GLuint index)
1579 {
1580 	if (index < s_n_texture_tragets)
1581 	{
1582 		return s_texture_infos[index].m_target;
1583 	}
1584 	else
1585 	{
1586 		return GL_TEXTURE_2D;
1587 	}
1588 }
1589 
1590 /** Replace first occurance of <token> with <text> in <string> starting at <search_posistion>
1591  *
1592  * @param token           Token string
1593  * @param search_position Position at which find will start, it is updated to position at which replaced text ends
1594  * @param text            String that will be used as replacement for <token>
1595  * @param string          String to work on
1596  **/
replaceToken(const GLchar * token,size_t & search_position,const GLchar * text,std::string & string)1597 void replaceToken(const GLchar* token, size_t& search_position, const GLchar* text, std::string& string)
1598 {
1599 	const size_t text_length	= strlen(text);
1600 	const size_t token_length   = strlen(token);
1601 	const size_t token_position = string.find(token, search_position);
1602 
1603 	string.replace(token_position, token_length, text, text_length);
1604 
1605 	search_position = token_position + text_length;
1606 }
1607 
1608 /** Constructor
1609  *
1610  * @param context Test context
1611  **/
ErrorsBindBuffersTest(deqp::Context & context)1612 ErrorsBindBuffersTest::ErrorsBindBuffersTest(deqp::Context& context)
1613 	: TestCase(context, "errors_bind_buffers", "Verifies that proper errors are generated by buffer binding routines")
1614 {
1615 	/* Nothing to be done */
1616 }
1617 
1618 /** Execute test
1619  *
1620  * @return tcu::TestNode::STOP
1621  **/
iterate()1622 tcu::TestNode::IterateResult ErrorsBindBuffersTest::iterate()
1623 {
1624 	const Functions& gl = m_context.getRenderContext().getFunctions();
1625 
1626 #if DEBUG_ENBALE_MESSAGE_CALLBACK
1627 	gl.debugMessageCallback(debug_proc, &m_context);
1628 	GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
1629 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
1630 
1631 	/* - INVALID_ENUM when <target> is not valid; */
1632 	{
1633 		static const GLintptr buffer_size = 16;
1634 		static const GLsizei  count		  = 1;
1635 		static const GLuint   first		  = 0;
1636 		static const GLintptr offset	  = 4;
1637 		static const GLintptr size		  = buffer_size - offset;
1638 
1639 		Buffer buffer;
1640 
1641 		buffer.InitData(m_context, GL_ARRAY_BUFFER, GL_DYNAMIC_COPY, buffer_size, 0 /* data */);
1642 
1643 		gl.bindBuffersBase(GL_ARRAY_BUFFER, first, count, &buffer.m_id);
1644 		CHECK_ERROR(GL_INVALID_ENUM, "BindBuffersBase with invalid <target>");
1645 
1646 		gl.bindBuffersRange(GL_ARRAY_BUFFER, first, count, &buffer.m_id, &offset, &size);
1647 		CHECK_ERROR(GL_INVALID_ENUM, "BindBuffersRange with invalid <target>");
1648 	}
1649 
1650 	for (size_t i = 0; i < s_n_buffer_tragets; ++i)
1651 	{
1652 		static const GLsizei n_buffers = 4;
1653 
1654 		const GLenum	   pname_alignment = s_buffer_infos[i].m_pname_alignment;
1655 		const GLenum	   pname_max	   = s_buffer_infos[i].m_pname_max;
1656 		const GLenum	   target		   = s_buffer_infos[i].m_target;
1657 		const std::string& target_name	 = glu::getBufferTargetStr(target).toString();
1658 
1659 		GLintptr buffer_size	  = 16;
1660 		GLsizei  count			  = n_buffers;
1661 		GLuint   first			  = 0;
1662 		GLuint   invalid_id		  = 1; /* Start with 1, as 0 is not valid name */
1663 		GLintptr offset			  = 4; /* ATOMIC and XFB require alignment of 4 */
1664 		GLint	offset_alignment = 1;
1665 		GLint	max_buffers	  = 0;
1666 		GLintptr size			  = buffer_size - offset;
1667 		size_t   validated_index  = n_buffers - 1;
1668 
1669 		/* Get alignment */
1670 		if (0 != pname_alignment)
1671 		{
1672 			gl.getIntegerv(pname_alignment, &offset_alignment);
1673 			GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1674 
1675 			buffer_size += offset_alignment;
1676 			offset = offset_alignment;
1677 			size   = buffer_size - offset;
1678 		}
1679 
1680 		/* Get max */
1681 		gl.getIntegerv(pname_max, &max_buffers);
1682 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1683 
1684 		/* Select count so <first + count> does not exceed max.
1685 		 * Validated index shall be in the specified range.
1686 		 */
1687 		if (n_buffers > max_buffers)
1688 		{
1689 			count			= max_buffers;
1690 			validated_index = max_buffers - 1;
1691 		}
1692 
1693 		/* Storage */
1694 		Buffer   buffer[n_buffers];
1695 		GLuint   buffer_ids[n_buffers];
1696 		GLintptr offsets[n_buffers];
1697 		GLintptr sizes[n_buffers];
1698 
1699 		/* Prepare buffers */
1700 		for (size_t j = 0; j < n_buffers; ++j)
1701 		{
1702 			buffer[j].InitData(m_context, target, GL_DYNAMIC_COPY, buffer_size, 0 /* data */);
1703 
1704 			buffer_ids[j] = buffer[j].m_id;
1705 			offsets[j]	= offset;
1706 			sizes[j]	  = size;
1707 		}
1708 
1709 		/* - INVALID_OPERATION when <first> + <count> is greater than allowed limit; */
1710 		{
1711 			GLsizei t_count = n_buffers;
1712 			GLuint  t_first = 0;
1713 
1714 			/* Select first so <first + count> exceeds max, avoid negative first */
1715 			if (n_buffers <= max_buffers)
1716 			{
1717 				t_first = max_buffers - n_buffers + 1;
1718 			}
1719 			else
1720 			{
1721 				t_count = max_buffers + 1;
1722 				/* first = 0; */
1723 			}
1724 
1725 			/* Test */
1726 			gl.bindBuffersBase(target, t_first, t_count, buffer_ids);
1727 			CHECK_ERROR(GL_INVALID_OPERATION,
1728 						"BindBuffersBase with invalid <first> + <count>, target: " << target_name);
1729 
1730 			gl.bindBuffersRange(target, t_first, t_count, buffer_ids, offsets, sizes);
1731 			CHECK_ERROR(GL_INVALID_OPERATION,
1732 						"BindBuffersRange with invalid <first> + <count>, target: " << target_name);
1733 		}
1734 
1735 		/* - INVALID_OPERATION if any value in <buffers> is not zero or the name of
1736 		 * existing buffer;
1737 		 */
1738 		{
1739 			GLuint t_buffer_ids[n_buffers];
1740 
1741 			memcpy(t_buffer_ids, buffer_ids, sizeof(buffer_ids));
1742 
1743 			/* Find invalid id */
1744 			while (1)
1745 			{
1746 				if (GL_TRUE != gl.isBuffer(invalid_id))
1747 				{
1748 					break;
1749 				}
1750 
1751 				invalid_id += 1;
1752 			}
1753 
1754 			/* Invalidate the entry */
1755 			t_buffer_ids[validated_index] = invalid_id;
1756 
1757 			/* Test */
1758 			gl.bindBuffersBase(target, first, count, t_buffer_ids);
1759 			CHECK_ERROR(GL_INVALID_OPERATION, "BindBuffersBase with invalid buffer id, target: " << target_name);
1760 
1761 			gl.bindBuffersRange(target, first, count, t_buffer_ids, offsets, sizes);
1762 			CHECK_ERROR(GL_INVALID_OPERATION, "BindBuffersRange with invalid buffer id, target: " << target_name);
1763 		}
1764 
1765 		/* - INVALID_VALUE if any value in <offsets> is less than zero; */
1766 		{
1767 			GLintptr t_offsets[n_buffers];
1768 			GLintptr t_sizes[n_buffers];
1769 
1770 			memcpy(t_offsets, offsets, sizeof(offsets));
1771 			memcpy(t_sizes, sizes, sizeof(sizes));
1772 
1773 			/* Invalidate the entry */
1774 			t_offsets[validated_index] = -1;
1775 			t_sizes[validated_index]   = -1;
1776 
1777 			/* Test */
1778 			gl.bindBuffersRange(target, first, count, buffer_ids, t_offsets, sizes);
1779 			CHECK_ERROR(GL_INVALID_VALUE, "BindBuffersRange with negative offset, target: " << target_name);
1780 
1781 			/* Test */
1782 			gl.bindBuffersRange(target, first, count, buffer_ids, offsets, t_sizes);
1783 			CHECK_ERROR(GL_INVALID_VALUE, "BindBuffersRange with negative size, target: " << target_name);
1784 		}
1785 
1786 		/* - INVALID_VALUE if any pair of <offsets> and <sizes> exceeds limits. */
1787 		{
1788 			GLintptr t_offsets[n_buffers];
1789 			GLintptr t_sizes[n_buffers];
1790 
1791 			memcpy(t_offsets, offsets, sizeof(offsets));
1792 			memcpy(t_sizes, sizes, sizeof(sizes));
1793 
1794 			/* Invalidate the entry */
1795 			t_offsets[validated_index] -= 1;	 /* Not aligned by required value */
1796 			t_sizes[validated_index] = size - 1; /* Not aligned by required value */
1797 
1798 			/* Test */
1799 			gl.bindBuffersRange(target, first, count, buffer_ids, t_offsets, sizes);
1800 			CHECK_ERROR(GL_INVALID_VALUE, "BindBuffersRange with invalid <offset>, target: " << target_name);
1801 
1802 			/* Test */
1803 			if (GL_TRANSFORM_FEEDBACK_BUFFER == target)
1804 			{
1805 				gl.bindBuffersRange(target, first, count, buffer_ids, offsets, t_sizes);
1806 				CHECK_ERROR(GL_INVALID_VALUE, "BindBuffersRange with invalid <size>, target: " << target_name);
1807 			}
1808 		}
1809 	}
1810 
1811 	/* Set result */
1812 	m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1813 
1814 	/* Done */
1815 	return tcu::TestNode::STOP;
1816 }
1817 
1818 /** Constructor
1819  *
1820  * @param context Test context
1821  **/
ErrorsBindTexturesTest(deqp::Context & context)1822 ErrorsBindTexturesTest::ErrorsBindTexturesTest(deqp::Context& context)
1823 	: TestCase(context, "errors_bind_textures", "Verifies that proper errors are generated by texture binding routines")
1824 {
1825 	/* Nothing to be done */
1826 }
1827 
1828 /** Execute test
1829  *
1830  * @return tcu::TestNode::STOP
1831  **/
iterate()1832 tcu::TestNode::IterateResult ErrorsBindTexturesTest::iterate()
1833 {
1834 	static const GLuint  depth		= 8;
1835 	static const GLuint  height		= 8;
1836 	static const GLsizei n_textures = 4;
1837 	static const GLuint  width		= 8;
1838 
1839 	const Functions& gl = m_context.getRenderContext().getFunctions();
1840 
1841 #if DEBUG_ENBALE_MESSAGE_CALLBACK
1842 	gl.debugMessageCallback(debug_proc, &m_context);
1843 	GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
1844 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
1845 
1846 	GLsizei count			= n_textures;
1847 	GLuint  first			= 0;
1848 	GLuint  invalid_id		= 1; /* Start with 1, as 0 is not valid name */
1849 	GLint   max_textures	= 0;
1850 	size_t  validated_index = n_textures - 1;
1851 
1852 	/* Get max */
1853 	gl.getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_textures);
1854 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1855 
1856 	/* Select count so <first + count> does not exceed max.
1857 	 * Validated index shall be in the specified range.
1858 	 */
1859 	if (n_textures > max_textures)
1860 	{
1861 		count			= max_textures;
1862 		validated_index = max_textures - 1;
1863 	}
1864 
1865 	/* Storage */
1866 	Texture texture[n_textures];
1867 	GLuint  texture_ids[n_textures];
1868 
1869 	/* Prepare textures */
1870 	texture[0].InitStorage(m_context, GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, width, height, depth);
1871 	texture[1].InitStorage(m_context, GL_TEXTURE_2D_ARRAY, 1 /* levels */, GL_RGBA8, width, height, depth);
1872 	texture[2].InitStorage(m_context, GL_TEXTURE_1D_ARRAY, 1 /* levels */, GL_RGBA8, width, height, depth);
1873 	texture[3].InitStorage(m_context, GL_TEXTURE_3D, 1 /* levels */, GL_RGBA8, width, height, depth);
1874 
1875 	for (size_t i = 0; i < n_textures; ++i)
1876 	{
1877 		texture_ids[i] = texture[i].m_id;
1878 	}
1879 
1880 	/* - INVALID_OPERATION when <first> + <count> exceed limits; */
1881 	{
1882 		GLsizei t_count = n_textures;
1883 		GLuint  t_first = 0;
1884 
1885 		/* Select first so <first + count> exceeds max, avoid negative first */
1886 		if (n_textures <= max_textures)
1887 		{
1888 			t_first = max_textures - n_textures + 1;
1889 		}
1890 		else
1891 		{
1892 			t_count = max_textures + 1;
1893 			/* first = 0; */
1894 		}
1895 
1896 		/* Test */
1897 		gl.bindTextures(t_first, t_count, texture_ids);
1898 		CHECK_ERROR(GL_INVALID_OPERATION, "BindTextures with invalid <first> + <count>");
1899 	}
1900 
1901 	/* - INVALID_OPERATION if any value in <buffers> is not zero or the name of
1902 	 * existing buffer;
1903 	 */
1904 	{
1905 		GLuint t_texture_ids[n_textures];
1906 
1907 		memcpy(t_texture_ids, texture_ids, sizeof(texture_ids));
1908 
1909 		/* Find invalid id */
1910 		while (1)
1911 		{
1912 			if (GL_TRUE != gl.isTexture(invalid_id))
1913 			{
1914 				break;
1915 			}
1916 
1917 			invalid_id += 1;
1918 		}
1919 
1920 		/* Invalidate the entry */
1921 		t_texture_ids[validated_index] = invalid_id;
1922 
1923 		/* Test */
1924 		gl.bindTextures(first, count, t_texture_ids);
1925 		CHECK_ERROR(GL_INVALID_OPERATION, "BindTextures with invalid texture id");
1926 	}
1927 
1928 	/* Set result */
1929 	m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1930 
1931 	/* Done */
1932 	return tcu::TestNode::STOP;
1933 }
1934 
1935 /** Constructor
1936  *
1937  * @param context Test context
1938  **/
ErrorsBindSamplersTest(deqp::Context & context)1939 ErrorsBindSamplersTest::ErrorsBindSamplersTest(deqp::Context& context)
1940 	: TestCase(context, "errors_bind_samplers", "Verifies that proper errors are generated by sampler binding routines")
1941 {
1942 	/* Nothing to be done */
1943 }
1944 
1945 /** Execute test
1946  *
1947  * @return tcu::TestNode::STOP
1948  **/
iterate()1949 tcu::TestNode::IterateResult ErrorsBindSamplersTest::iterate()
1950 {
1951 	static const GLsizei n_samplers = 4;
1952 
1953 	const Functions& gl = m_context.getRenderContext().getFunctions();
1954 
1955 #if DEBUG_ENBALE_MESSAGE_CALLBACK
1956 	gl.debugMessageCallback(debug_proc, &m_context);
1957 	GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
1958 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
1959 
1960 	GLsizei count			= n_samplers;
1961 	GLuint  first			= 0;
1962 	GLuint  invalid_id		= 1; /* Start with 1, as 0 is not valid name */
1963 	GLint   max_samplers	= 0;
1964 	size_t  validated_index = n_samplers - 1;
1965 
1966 	/* Get max */
1967 	gl.getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_samplers);
1968 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1969 
1970 	/* Select count so <first + count> does not exceed max.
1971 	 * Validated index shall be in the specified range.
1972 	 */
1973 	if (n_samplers > max_samplers)
1974 	{
1975 		count			= max_samplers;
1976 		validated_index = max_samplers - 1;
1977 	}
1978 
1979 	/* Storage */
1980 	GLuint sampler_ids[n_samplers];
1981 
1982 	/* Prepare samplers */
1983 	gl.genSamplers(n_samplers, sampler_ids);
1984 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenSamplers");
1985 
1986 	try
1987 	{
1988 		/* - INVALID_OPERATION when <first> + <count> exceed limits; */
1989 		{
1990 			GLsizei t_count = n_samplers;
1991 			GLuint  t_first = 0;
1992 
1993 			/* Select first so <first + count> exceeds max, avoid negative first */
1994 			if (n_samplers <= max_samplers)
1995 			{
1996 				t_first = max_samplers - n_samplers + 1;
1997 			}
1998 			else
1999 			{
2000 				t_count = max_samplers + 1;
2001 				/* first = 0; */
2002 			}
2003 
2004 			/* Test */
2005 			gl.bindSamplers(t_first, t_count, sampler_ids);
2006 			CHECK_ERROR(GL_INVALID_OPERATION, "BindSamplers with invalid <first> + <count>");
2007 		}
2008 
2009 		/* - INVALID_OPERATION if any value in <buffers> is not zero or the name of
2010 		 * existing buffer;
2011 		 */
2012 		{
2013 			GLuint t_sampler_ids[n_samplers];
2014 
2015 			memcpy(t_sampler_ids, sampler_ids, sizeof(sampler_ids));
2016 
2017 			/* Find invalid id */
2018 			while (1)
2019 			{
2020 				if (GL_TRUE != gl.isTexture(invalid_id))
2021 				{
2022 					break;
2023 				}
2024 
2025 				invalid_id += 1;
2026 			}
2027 
2028 			/* Invalidate the entry */
2029 			t_sampler_ids[validated_index] = invalid_id;
2030 
2031 			/* Test */
2032 			gl.bindTextures(first, count, t_sampler_ids);
2033 			CHECK_ERROR(GL_INVALID_OPERATION, "BindSamplers with invalid sampler id");
2034 		}
2035 	}
2036 	catch (const std::exception&)
2037 	{
2038 		gl.deleteSamplers(n_samplers, sampler_ids);
2039 
2040 		TCU_FAIL("Invalid error generated");
2041 	}
2042 
2043 	/* Delete samplers */
2044 	gl.deleteSamplers(n_samplers, sampler_ids);
2045 
2046 	/* Set result */
2047 	m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2048 
2049 	/* Done */
2050 	return tcu::TestNode::STOP;
2051 }
2052 
2053 /** Constructor
2054  *
2055  * @param context Test context
2056  **/
ErrorsBindImageTexturesTest(deqp::Context & context)2057 ErrorsBindImageTexturesTest::ErrorsBindImageTexturesTest(deqp::Context& context)
2058 	: TestCase(context, "errors_bind_image_textures",
2059 			   "Verifies that proper errors are generated by image binding routines")
2060 {
2061 	/* Nothing to be done */
2062 }
2063 
2064 /** Execute test
2065  *
2066  * @return tcu::TestNode::STOP
2067  **/
iterate()2068 tcu::TestNode::IterateResult ErrorsBindImageTexturesTest::iterate()
2069 {
2070 	static const GLuint  depth		= 8;
2071 	static const GLuint  height		= 8;
2072 	static const GLsizei n_textures = 4;
2073 	static const GLuint  width		= 8;
2074 
2075 	const Functions& gl = m_context.getRenderContext().getFunctions();
2076 
2077 #if DEBUG_ENBALE_MESSAGE_CALLBACK
2078 	gl.debugMessageCallback(debug_proc, &m_context);
2079 	GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
2080 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
2081 
2082 	GLsizei count			= n_textures;
2083 	GLuint  first			= 0;
2084 	GLuint  invalid_id		= 1; /* Start with 1, as 0 is not valid name */
2085 	GLint   max_textures	= 0;
2086 	size_t  validated_index = n_textures - 1;
2087 
2088 	/* Get max */
2089 	gl.getIntegerv(GL_MAX_IMAGE_UNITS, &max_textures);
2090 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2091 
2092 	/* Select count so <first + count> does not exceed max.
2093 	 * Validated index shall be in the specified range.
2094 	 */
2095 	if (n_textures > max_textures)
2096 	{
2097 		count			= max_textures;
2098 		validated_index = max_textures - 1;
2099 	}
2100 
2101 	/* Storage */
2102 	Texture texture[n_textures];
2103 	GLuint  texture_ids[n_textures];
2104 
2105 	/* Prepare textures */
2106 	texture[0].InitStorage(m_context, GL_TEXTURE_2D, 1, GL_RGBA8, width, height, depth);
2107 	texture[1].InitStorage(m_context, GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, width, height, depth);
2108 	texture[2].InitStorage(m_context, GL_TEXTURE_1D_ARRAY, 1, GL_RGBA8, width, height, depth);
2109 	texture[3].InitStorage(m_context, GL_TEXTURE_3D, 1, GL_RGBA8, width, height, depth);
2110 
2111 	for (size_t i = 0; i < n_textures; ++i)
2112 	{
2113 		texture_ids[i] = texture[i].m_id;
2114 	}
2115 
2116 	/* - INVALID_OPERATION when <first> + <count> exceed limits; */
2117 	{
2118 		GLsizei t_count = n_textures;
2119 		GLuint  t_first = 0;
2120 
2121 		/* Select first so <first + count> exceeds max, avoid negative first */
2122 		if (n_textures <= max_textures)
2123 		{
2124 			t_first = max_textures - n_textures + 1;
2125 		}
2126 		else
2127 		{
2128 			t_count = max_textures + 1;
2129 			/* first = 0; */
2130 		}
2131 
2132 		/* Test */
2133 		gl.bindImageTextures(t_first, t_count, texture_ids);
2134 		CHECK_ERROR(GL_INVALID_OPERATION, "BindImageTextures with invalid <first> + <count>");
2135 	}
2136 
2137 	/* - INVALID_OPERATION if any value in <buffers> is not zero or the name of
2138 	 * existing buffer;
2139 	 */
2140 	{
2141 		GLuint t_texture_ids[n_textures];
2142 
2143 		memcpy(t_texture_ids, texture_ids, sizeof(texture_ids));
2144 
2145 		/* Find invalid id */
2146 		while (1)
2147 		{
2148 			if (GL_TRUE != gl.isTexture(invalid_id))
2149 			{
2150 				break;
2151 			}
2152 
2153 			invalid_id += 1;
2154 		}
2155 
2156 		/* Invalidate the entry */
2157 		t_texture_ids[validated_index] = invalid_id;
2158 
2159 		/* Test */
2160 		gl.bindImageTextures(first, count, t_texture_ids);
2161 		CHECK_ERROR(GL_INVALID_OPERATION, "BindImageTextures with invalid texture id");
2162 	}
2163 
2164 	/* - INVALID_OPERATION if any entry found in <textures> has invalid internal
2165 	 * format at level 0;
2166 	 */
2167 	{
2168 		GLuint t_texture_ids[n_textures];
2169 
2170 		memcpy(t_texture_ids, texture_ids, sizeof(texture_ids));
2171 
2172 		/* Prepare texture with invalid format */
2173 		Texture t_texture;
2174 		t_texture.Init(m_context);
2175 		t_texture.Generate(gl, t_texture.m_id);
2176 		t_texture.Bind(gl, t_texture.m_id, GL_TEXTURE_2D);
2177 		gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGB9_E5, width, 0);
2178 		CHECK_ERROR(GL_INVALID_VALUE, "texStorage2D has height set to 0");
2179 
2180 		/* Invalidate the entry */
2181 		t_texture_ids[validated_index] = t_texture.m_id;
2182 
2183 		/* Test */
2184 		gl.bindImageTextures(first, count, t_texture_ids);
2185 		CHECK_ERROR(GL_INVALID_OPERATION, "BindImageTextures with invalid internal format");
2186 	}
2187 
2188 	/* - INVALID_VALUE when any entry in <textures> has any of dimensions equal
2189 	 * to 0 at level 0.
2190 	 */
2191 	{
2192 		GLuint t_texture_ids[n_textures];
2193 
2194 		memcpy(t_texture_ids, texture_ids, sizeof(texture_ids));
2195 
2196 		/* Prepare texture with invalid format */
2197 		Texture t_texture;
2198 		t_texture.InitStorage(m_context, GL_TEXTURE_2D, 1, GL_RGB9_E5, width, 0, depth, true);
2199 
2200 		/* Invalidate the entry */
2201 		t_texture_ids[validated_index] = t_texture.m_id;
2202 
2203 		/* Test */
2204 		gl.bindImageTextures(first, count, t_texture_ids);
2205 		CHECK_ERROR(GL_INVALID_VALUE, "BindImageTextures with 2D texture that has height set to 0");
2206 	}
2207 
2208 	/* Set result */
2209 	m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2210 
2211 	/* Done */
2212 	return tcu::TestNode::STOP;
2213 }
2214 
2215 /** Constructor
2216  *
2217  * @param context Test context
2218  **/
ErrorsBindVertexBuffersTest(deqp::Context & context)2219 ErrorsBindVertexBuffersTest::ErrorsBindVertexBuffersTest(deqp::Context& context)
2220 	: TestCase(context, "errors_bind_vertex_buffers",
2221 			   "Verifies that proper errors are generated by vertex buffer binding routines")
2222 {
2223 	/* Nothing to be done */
2224 }
2225 
2226 /** Execute test
2227  *
2228  * @return tcu::TestNode::STOP
2229  **/
iterate()2230 tcu::TestNode::IterateResult ErrorsBindVertexBuffersTest::iterate()
2231 {
2232 	const Functions& gl = m_context.getRenderContext().getFunctions();
2233 
2234 #if DEBUG_ENBALE_MESSAGE_CALLBACK
2235 	gl.debugMessageCallback(debug_proc, &m_context);
2236 	GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
2237 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
2238 
2239 	static const GLsizei n_buffers = 4;
2240 	static const GLsizei stride	= 4;
2241 
2242 	GLintptr buffer_size	 = 16;
2243 	GLsizei  count			 = n_buffers;
2244 	GLuint   first			 = 0;
2245 	GLuint   invalid_id		 = 1; /* Start with 1, as 0 is not valid name */
2246 	GLintptr offset			 = 4; /* ATOMIC and XFB require alignment of 4 */
2247 	GLint	max_buffers	 = 0;
2248 	size_t   validated_index = n_buffers - 1;
2249 
2250 	/* Get max */
2251 	gl.getIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &max_buffers);
2252 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2253 
2254 	/* Select count so <first + count> does not exceed max.
2255 	 * Validated index shall be in the specified range.
2256 	 */
2257 	if (n_buffers > max_buffers)
2258 	{
2259 		count			= max_buffers;
2260 		validated_index = max_buffers - 1;
2261 	}
2262 
2263 	/* Storage */
2264 	Buffer   buffer[n_buffers];
2265 	GLuint   buffer_ids[n_buffers];
2266 	GLintptr offsets[n_buffers];
2267 	GLsizei  strides[n_buffers];
2268 
2269 	/* Prepare buffers */
2270 	for (size_t j = 0; j < n_buffers; ++j)
2271 	{
2272 		buffer[j].InitData(m_context, GL_ARRAY_BUFFER, GL_DYNAMIC_COPY, buffer_size, 0 /* data */);
2273 
2274 		buffer_ids[j] = buffer[j].m_id;
2275 		offsets[j]	= offset;
2276 		strides[j]	= stride;
2277 	}
2278 
2279 	/* Prepare VAO */
2280 	GLuint vao = 0;
2281 	gl.genVertexArrays(1, &vao);
2282 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
2283 	try
2284 	{
2285 		gl.bindVertexArray(vao);
2286 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArrays");
2287 
2288 		/* - INVALID_OPERATION when <first> + <count> exceeds limits; */
2289 		{
2290 			GLsizei t_count = n_buffers;
2291 			GLuint  t_first = 0;
2292 
2293 			/* Select first so <first + count> exceeds max, avoid negative first */
2294 			if (n_buffers <= max_buffers)
2295 			{
2296 				t_first = max_buffers - n_buffers + 1;
2297 			}
2298 			else
2299 			{
2300 				t_count = max_buffers + 1;
2301 				/* first = 0; */
2302 			}
2303 
2304 			/* Test */
2305 			gl.bindVertexBuffers(t_first, t_count, buffer_ids, offsets, strides);
2306 			CHECK_ERROR(GL_INVALID_OPERATION, "BindVertexBuffers with invalid <first> + <count>");
2307 		}
2308 
2309 		/* - INVALID_OPERATION if any value in <buffers> is not zero or the name of
2310 		 * existing buffer;
2311 		 */
2312 		{
2313 			GLuint t_buffer_ids[n_buffers];
2314 
2315 			memcpy(t_buffer_ids, buffer_ids, sizeof(buffer_ids));
2316 
2317 			/* Find invalid id */
2318 			while (1)
2319 			{
2320 				if (GL_TRUE != gl.isBuffer(invalid_id))
2321 				{
2322 					break;
2323 				}
2324 
2325 				invalid_id += 1;
2326 			}
2327 
2328 			/* Invalidate the entry */
2329 			t_buffer_ids[validated_index] = invalid_id;
2330 
2331 			/* Test */
2332 			gl.bindVertexBuffers(first, count, t_buffer_ids, offsets, strides);
2333 			CHECK_ERROR(GL_INVALID_OPERATION, "BindVertexBuffers with invalid buffer id");
2334 		}
2335 
2336 		/* - INVALID_VALUE if any value in <offsets> or <strides> is less than zero. */
2337 		{
2338 			GLintptr t_offsets[n_buffers];
2339 			GLsizei  t_strides[n_buffers];
2340 
2341 			memcpy(t_offsets, offsets, sizeof(offsets));
2342 			memcpy(t_strides, strides, sizeof(strides));
2343 
2344 			/* Invalidate the entry */
2345 			t_offsets[validated_index] = -1;
2346 			t_strides[validated_index] = -1;
2347 
2348 			/* Test */
2349 			gl.bindVertexBuffers(first, count, buffer_ids, t_offsets, strides);
2350 			CHECK_ERROR(GL_INVALID_VALUE, "BindVertexBuffers with negative offset");
2351 
2352 			gl.bindVertexBuffers(first, count, buffer_ids, offsets, t_strides);
2353 			CHECK_ERROR(GL_INVALID_VALUE, "BindVertexBuffers with negative stride");
2354 		}
2355 	}
2356 	catch (const std::exception&)
2357 	{
2358 		gl.deleteVertexArrays(1, &vao);
2359 		TCU_FAIL("Unexpected error generated");
2360 	}
2361 
2362 	gl.deleteVertexArrays(1, &vao);
2363 	GLU_EXPECT_NO_ERROR(gl.getError(), "DeleteVertexArrays");
2364 
2365 	/* Set result */
2366 	m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2367 
2368 	/* Done */
2369 	return tcu::TestNode::STOP;
2370 }
2371 
2372 /** Constructor
2373  *
2374  * @param context Test context
2375  **/
FunctionalBindBuffersBaseTest(deqp::Context & context)2376 FunctionalBindBuffersBaseTest::FunctionalBindBuffersBaseTest(deqp::Context& context)
2377 	: TestCase(context, "functional_bind_buffers_base", "Verifies that BindBuffersBase works as expected")
2378 {
2379 	/* Nothing to be done */
2380 }
2381 
2382 /** Execute test
2383  *
2384  * @return tcu::TestNode::STOP
2385  **/
iterate()2386 tcu::TestNode::IterateResult FunctionalBindBuffersBaseTest::iterate()
2387 {
2388 	const Functions& gl = m_context.getRenderContext().getFunctions();
2389 
2390 #if DEBUG_ENBALE_MESSAGE_CALLBACK
2391 	gl.debugMessageCallback(debug_proc, &m_context);
2392 	GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
2393 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
2394 
2395 	for (size_t i = 0; i < s_n_buffer_tragets; ++i)
2396 	{
2397 		const GLenum	   pname_binding  = s_buffer_infos[i].m_pname_binding;
2398 		const GLenum	   pname_max	  = s_buffer_infos[i].m_pname_max;
2399 		const GLenum	   pname_max_size = s_buffer_infos[i].m_pname_max_size;
2400 		const GLenum	   target		  = s_buffer_infos[i].m_target;
2401 		const std::string& target_name	= glu::getBufferTargetStr(target).toString();
2402 
2403 		GLint max_buffers = 0;
2404 		GLint max_size	= 0;
2405 
2406 		/* Get max */
2407 		gl.getIntegerv(pname_max, &max_buffers);
2408 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2409 
2410 		/* Get max size */
2411 		gl.getIntegerv(pname_max_size, &max_size);
2412 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2413 
2414 		GLintptr buffer_size = max_size / max_buffers;
2415 
2416 		/* Storage */
2417 		std::vector<Buffer> buffer;
2418 		std::vector<GLuint> buffer_ids;
2419 
2420 		buffer.resize(max_buffers);
2421 		buffer_ids.resize(max_buffers);
2422 
2423 		/* Prepare buffers */
2424 		for (GLint j = 0; j < max_buffers; ++j)
2425 		{
2426 			buffer[j].InitData(m_context, target, GL_DYNAMIC_COPY, buffer_size, 0 /* data */);
2427 
2428 			buffer_ids[j] = buffer[j].m_id;
2429 		}
2430 
2431 		/*
2432 		 * - execute BindBufferBase to bind all buffers to tested target;
2433 		 * - inspect if bindings were modified;
2434 		 */
2435 		gl.bindBuffersBase(target, 0 /* first */, max_buffers /* count */, &buffer_ids[0]);
2436 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersBase");
2437 
2438 		for (GLint j = 0; j < max_buffers; ++j)
2439 		{
2440 			checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]);
2441 		}
2442 
2443 		/*
2444 		 *
2445 		 * - execute BindBufferBase for first half of bindings with NULL as <buffers>
2446 		 * to unbind first half of bindings for tested target;
2447 		 * - inspect if bindings were modified;
2448 		 * - execute BindBufferBase for second half of bindings with NULL as <buffers>
2449 		 * to unbind rest of bindings;
2450 		 * - inspect if bindings were modified;
2451 		 */
2452 		GLint half_index = max_buffers / 2;
2453 		gl.bindBuffersBase(target, 0 /* first */, half_index /* count */, 0);
2454 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersBase");
2455 
2456 		for (GLint j = 0; j < half_index; ++j)
2457 		{
2458 			checkBinding(m_context, pname_binding, j, target_name, 0);
2459 		}
2460 
2461 		for (GLint j = half_index; j < max_buffers; ++j)
2462 		{
2463 			checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]);
2464 		}
2465 
2466 		gl.bindBuffersBase(target, half_index /* first */, max_buffers - half_index /* count */, 0);
2467 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersBase");
2468 
2469 		for (GLint j = 0; j < max_buffers; ++j)
2470 		{
2471 			checkBinding(m_context, pname_binding, j, target_name, 0);
2472 		}
2473 
2474 		/*
2475 		 * - change <buffers> so first entry is invalid;
2476 		 * - execute BindBufferBase to bind all buffers to tested target; It is
2477 		 * expected that INVALID_OPERATION will be generated;
2478 		 * - inspect if all bindings but first were modified;
2479 		 */
2480 
2481 		/* Find invalid id */
2482 		GLuint invalid_id = 1;
2483 		while (1)
2484 		{
2485 			if (GL_TRUE != gl.isBuffer(invalid_id))
2486 			{
2487 				break;
2488 			}
2489 
2490 			invalid_id += 1;
2491 		}
2492 
2493 		buffer_ids[0] = invalid_id;
2494 
2495 		gl.bindBuffersBase(target, 0 /* first */, max_buffers /* count */, &buffer_ids[0]);
2496 		CHECK_ERROR(GL_INVALID_OPERATION, "BindBufferBase with invalid buffer id");
2497 
2498 		/* Update buffer_ids */
2499 		buffer_ids[0] = 0; /* 0 means unbound */
2500 
2501 		for (GLint j = 0; j < max_buffers; ++j)
2502 		{
2503 			checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]);
2504 		}
2505 
2506 		/*
2507 		 * - bind any buffer to first binding;
2508 		 * - execute BindBufferBase for 0 as <first>, 1 as <count> and <buffers> filled
2509 		 * with zeros to unbind 1st binding for tested target;
2510 		 * - inspect if bindings were modified;
2511 		 */
2512 		gl.bindBufferBase(target, 0, buffer[0].m_id);
2513 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferBase");
2514 		checkBinding(m_context, pname_binding, 0, target_name, buffer[0].m_id);
2515 
2516 		std::vector<GLuint> t_buffer_ids;
2517 		t_buffer_ids.resize(max_buffers);
2518 
2519 		gl.bindBuffersBase(target, 0 /* first */, 1 /* count */, &t_buffer_ids[0]);
2520 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersBase");
2521 
2522 		for (GLint j = 0; j < max_buffers; ++j)
2523 		{
2524 			checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]);
2525 		}
2526 
2527 		/* - unbind all buffers. */
2528 		gl.bindBuffersBase(target, 0 /* first */, max_buffers /* count */, 0);
2529 	}
2530 
2531 	/* Set result */
2532 	m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2533 
2534 	/* Done */
2535 	return tcu::TestNode::STOP;
2536 }
2537 
2538 /** Constructor
2539  *
2540  * @param context Test context
2541  **/
FunctionalBindBuffersRangeTest(deqp::Context & context)2542 FunctionalBindBuffersRangeTest::FunctionalBindBuffersRangeTest(deqp::Context& context)
2543 	: TestCase(context, "functional_bind_buffers_range", "Verifies that BindBuffersRange works as expected")
2544 {
2545 	/* Nothing to be done */
2546 }
2547 
2548 /** Execute test
2549  *
2550  * @return tcu::TestNode::STOP
2551  **/
iterate()2552 tcu::TestNode::IterateResult FunctionalBindBuffersRangeTest::iterate()
2553 {
2554 	const Functions& gl = m_context.getRenderContext().getFunctions();
2555 
2556 #if DEBUG_ENBALE_MESSAGE_CALLBACK
2557 	gl.debugMessageCallback(debug_proc, &m_context);
2558 	GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
2559 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
2560 
2561 	for (size_t i = 0; i < s_n_buffer_tragets; ++i)
2562 	{
2563 		const GLenum	   pname_binding  = s_buffer_infos[i].m_pname_binding;
2564 		const GLenum	   pname_max	  = s_buffer_infos[i].m_pname_max;
2565 		const GLenum	   pname_max_size = s_buffer_infos[i].m_pname_max_size;
2566 		const GLenum	   target		  = s_buffer_infos[i].m_target;
2567 		const std::string& target_name	= glu::getBufferTargetStr(target).toString();
2568 
2569 		GLint max_buffers = 0;
2570 		GLint max_size	= 0;
2571 
2572 		/* Get max */
2573 		gl.getIntegerv(pname_max, &max_buffers);
2574 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2575 
2576 		/* Get max size */
2577 		gl.getIntegerv(pname_max_size, &max_size);
2578 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2579 
2580 		GLintptr buffer_size = max_size / max_buffers;
2581 
2582 		/* Storage */
2583 		std::vector<Buffer>		buffer;
2584 		std::vector<GLuint>		buffer_ids;
2585 		std::vector<GLintptr>   offsets;
2586 		std::vector<GLsizeiptr> sizes;
2587 
2588 		buffer.resize(max_buffers);
2589 		buffer_ids.resize(max_buffers);
2590 		offsets.resize(max_buffers);
2591 		sizes.resize(max_buffers);
2592 
2593 		/* Prepare buffers */
2594 		for (GLint j = 0; j < max_buffers; ++j)
2595 		{
2596 			buffer[j].InitData(m_context, target, GL_DYNAMIC_COPY, buffer_size, 0 /* data */);
2597 
2598 			buffer_ids[j] = buffer[j].m_id;
2599 			offsets[j]	= 0;
2600 			sizes[j]	  = buffer_size;
2601 		}
2602 
2603 		/*
2604 		 * - execute BindBufferBase to bind all buffers to tested target;
2605 		 * - inspect if bindings were modified;
2606 		 */
2607 		gl.bindBuffersRange(target, 0 /* first */, max_buffers /* count */, &buffer_ids[0], &offsets[0], &sizes[0]);
2608 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersRange");
2609 
2610 		for (GLint j = 0; j < max_buffers; ++j)
2611 		{
2612 			checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]);
2613 		}
2614 
2615 		/*
2616 		 *
2617 		 * - execute BindBufferBase for first half of bindings with NULL as <buffers>
2618 		 * to unbind first half of bindings for tested target;
2619 		 * - inspect if bindings were modified;
2620 		 * - execute BindBufferBase for second half of bindings with NULL as <buffers>
2621 		 * to unbind rest of bindings;
2622 		 * - inspect if bindings were modified;
2623 		 */
2624 		GLint half_index = max_buffers / 2;
2625 		gl.bindBuffersRange(target, 0 /* first */, half_index /* count */, 0, &offsets[0], &sizes[0]);
2626 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersRange");
2627 
2628 		for (GLint j = 0; j < half_index; ++j)
2629 		{
2630 			checkBinding(m_context, pname_binding, j, target_name, 0);
2631 		}
2632 
2633 		for (GLint j = half_index; j < max_buffers; ++j)
2634 		{
2635 			checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]);
2636 		}
2637 
2638 		gl.bindBuffersRange(target, half_index /* first */, max_buffers - half_index /* count */, 0, &offsets[0],
2639 							&sizes[0]);
2640 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersRange");
2641 
2642 		for (GLint j = 0; j < max_buffers; ++j)
2643 		{
2644 			checkBinding(m_context, pname_binding, j, target_name, 0);
2645 		}
2646 
2647 		/*
2648 		 * - change <buffers> so first entry is invalid;
2649 		 * - execute BindBufferBase to bind all buffers to tested target; It is
2650 		 * expected that INVALID_OPERATION will be generated;
2651 		 * - inspect if all bindings but first were modified;
2652 		 */
2653 
2654 		/* Find invalid id */
2655 		GLuint invalid_id = 1;
2656 		while (1)
2657 		{
2658 			if (GL_TRUE != gl.isBuffer(invalid_id))
2659 			{
2660 				break;
2661 			}
2662 
2663 			invalid_id += 1;
2664 		}
2665 
2666 		buffer_ids[0] = invalid_id;
2667 
2668 		gl.bindBuffersRange(target, 0 /* first */, max_buffers /* count */, &buffer_ids[0], &offsets[0], &sizes[0]);
2669 		CHECK_ERROR(GL_INVALID_OPERATION, "BindBuffersRange with invalid buffer id");
2670 
2671 		/* Update buffer_ids */
2672 		buffer_ids[0] = 0; /* 0 means unbound */
2673 
2674 		for (GLint j = 0; j < max_buffers; ++j)
2675 		{
2676 			checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]);
2677 		}
2678 
2679 		/*
2680 		 * - bind any buffer to first binding;
2681 		 * - execute BindBufferBase for 0 as <first>, 1 as <count> and <buffers> filled
2682 		 * with zeros to unbind 1st binding for tested target;
2683 		 * - inspect if bindings were modified;
2684 		 */
2685 		gl.bindBufferBase(target, 0, buffer[0].m_id);
2686 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferBase");
2687 		checkBinding(m_context, pname_binding, 0, target_name, buffer[0].m_id);
2688 
2689 		std::vector<GLuint> t_buffer_ids;
2690 		t_buffer_ids.resize(max_buffers);
2691 
2692 		gl.bindBuffersRange(target, 0 /* first */, 1 /* count */, &t_buffer_ids[0], &offsets[0], &sizes[0]);
2693 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersRange");
2694 
2695 		for (GLint j = 0; j < max_buffers; ++j)
2696 		{
2697 			checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]);
2698 		}
2699 
2700 		/* - unbind all buffers. */
2701 		gl.bindBuffersBase(target, 0 /* first */, max_buffers /* count */, 0);
2702 	}
2703 
2704 	/* Set result */
2705 	m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2706 
2707 	/* Done */
2708 	return tcu::TestNode::STOP;
2709 }
2710 
2711 /** Constructor
2712  *
2713  * @param context Test context
2714  **/
FunctionalBindTexturesTest(deqp::Context & context)2715 FunctionalBindTexturesTest::FunctionalBindTexturesTest(deqp::Context& context)
2716 	: TestCase(context, "functional_bind_textures", "Verifies that BindTextures works as expected")
2717 {
2718 	/* Nothing to be done */
2719 }
2720 
2721 /** Execute test
2722  *
2723  * @return tcu::TestNode::STOP
2724  **/
iterate()2725 tcu::TestNode::IterateResult FunctionalBindTexturesTest::iterate()
2726 {
2727 	static const GLuint depth  = 6;
2728 	static const GLuint height = 6;
2729 	static const GLuint width  = 6;
2730 
2731 	const Functions& gl = m_context.getRenderContext().getFunctions();
2732 
2733 #if DEBUG_ENBALE_MESSAGE_CALLBACK
2734 	gl.debugMessageCallback(debug_proc, &m_context);
2735 	GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
2736 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
2737 
2738 	GLuint invalid_id   = 1; /* Start with 1, as 0 is not valid name */
2739 	GLint  max_textures = 0;
2740 
2741 	/* Get max */
2742 	gl.getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_textures);
2743 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2744 
2745 	/* Storage */
2746 	Buffer				 buffer;
2747 	std::vector<Texture> texture;
2748 	std::vector<GLuint>  texture_ids;
2749 	std::vector<GLuint>  t_texture_ids;
2750 
2751 	texture.resize(max_textures);
2752 	texture_ids.resize(max_textures);
2753 	t_texture_ids.resize(max_textures);
2754 
2755 	/* Prepare buffer */
2756 	buffer.InitData(m_context, GL_TEXTURE_BUFFER, GL_DYNAMIC_COPY, 16 /* size */, 0 /* data */);
2757 
2758 	/* Prepare textures */
2759 	for (size_t i = 0; i < s_n_texture_tragets; ++i)
2760 	{
2761 		const GLenum target = s_texture_infos[i].m_target;
2762 
2763 		if (GL_TEXTURE_BUFFER != target)
2764 		{
2765 			texture[i].InitStorage(m_context, target, 1, GL_RGBA8, width, height, depth);
2766 		}
2767 		else
2768 		{
2769 			texture[i].InitBuffer(m_context, GL_RGBA8, buffer.m_id);
2770 		}
2771 
2772 		/* Unbind */
2773 		Texture::Bind(gl, 0, target);
2774 	}
2775 
2776 	for (GLint i = s_n_texture_tragets; i < max_textures; ++i)
2777 	{
2778 		texture[i].InitStorage(m_context, GL_TEXTURE_2D, 1, GL_RGBA8, width, height, depth);
2779 	}
2780 
2781 	/* Unbind */
2782 	Texture::Bind(gl, 0, GL_TEXTURE_2D);
2783 
2784 	for (GLint i = 0; i < max_textures; ++i)
2785 	{
2786 		texture_ids[i] = texture[i].m_id;
2787 	}
2788 
2789 	/*
2790 	 * - execute BindTextures to bind all textures;
2791 	 * - inspect bindings of all texture units to verify that proper bindings were
2792 	 * set;
2793 	 */
2794 	gl.bindTextures(0, max_textures, &texture_ids[0]);
2795 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindTextures");
2796 
2797 	for (GLint i = 0; i < max_textures; ++i)
2798 	{
2799 		checkTextureBinding(m_context, getBinding(i), i, texture_ids[i]);
2800 	}
2801 
2802 	/*
2803 	 * - execute BindTextures for the first half of units with <textures> filled
2804 	 * with zeros, to unbind those units;
2805 	 * - inspect bindings of all texture units to verify that proper bindings were
2806 	 * unbound;
2807 	 */
2808 	GLint half_index = max_textures / 2;
2809 
2810 	for (GLint i = 0; i < max_textures; ++i)
2811 	{
2812 		t_texture_ids[i] = 0;
2813 	}
2814 
2815 	gl.bindTextures(0, half_index, &t_texture_ids[0]);
2816 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindTextures");
2817 
2818 	for (GLint i = 0; i < half_index; ++i)
2819 	{
2820 		checkTextureBinding(m_context, getBinding(i), i, 0);
2821 	}
2822 
2823 	for (GLint i = half_index; i < max_textures; ++i)
2824 	{
2825 		checkTextureBinding(m_context, getBinding(i), i, texture_ids[i]);
2826 	}
2827 
2828 	/*
2829 	 * - execute BindTextures for the second half of units with NULL as<textures>,
2830 	 * to unbind those units;
2831 	 * - inspect bindings of all texture units to verify that proper bindings were
2832 	 * unbound;
2833 	 */
2834 	gl.bindTextures(half_index, max_textures - half_index, 0);
2835 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindTextures");
2836 
2837 	for (GLint i = 0; i < max_textures; ++i)
2838 	{
2839 		checkTextureBinding(m_context, getBinding(i), i, 0);
2840 	}
2841 
2842 	/*
2843 	 * - modify <textures> so first entry is invalid;
2844 	 * - execute BindTextures to bind all textures; It is expected that
2845 	 * INVALID_OPERATION will be generated;
2846 	 * - inspect bindings of all texture units to verify that proper bindings were
2847 	 * set;
2848 	 */
2849 
2850 	/* Find invalid id */
2851 	while (1)
2852 	{
2853 		if (GL_TRUE != gl.isTexture(invalid_id))
2854 		{
2855 			break;
2856 		}
2857 
2858 		invalid_id += 1;
2859 	}
2860 
2861 	/* Set invalid id */
2862 	texture_ids[0] = invalid_id;
2863 
2864 	gl.bindTextures(0, max_textures, &texture_ids[0]);
2865 	CHECK_ERROR(GL_INVALID_OPERATION, "BindTextures with invalid texture id");
2866 
2867 	checkTextureBinding(m_context, getBinding(0), 0, 0);
2868 	for (GLint i = 1; i < max_textures; ++i)
2869 	{
2870 		checkTextureBinding(m_context, getBinding(i), i, texture_ids[i]);
2871 	}
2872 
2873 	/* - unbind all textures. */
2874 	gl.bindTextures(0, max_textures, 0);
2875 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindTextures");
2876 
2877 	/* Set result */
2878 	m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2879 
2880 	/* Done */
2881 	return tcu::TestNode::STOP;
2882 }
2883 
2884 /** Constructor
2885  *
2886  * @param context Test context
2887  **/
FunctionalBindSamplersTest(deqp::Context & context)2888 FunctionalBindSamplersTest::FunctionalBindSamplersTest(deqp::Context& context)
2889 	: TestCase(context, "functional_bind_samplers", "Verifies that BindSamplers works as expected")
2890 {
2891 	/* Nothing to be done */
2892 }
2893 
2894 /** Execute test
2895  *
2896  * @return tcu::TestNode::STOP
2897  **/
iterate()2898 tcu::TestNode::IterateResult FunctionalBindSamplersTest::iterate()
2899 {
2900 	const Functions& gl = m_context.getRenderContext().getFunctions();
2901 
2902 #if DEBUG_ENBALE_MESSAGE_CALLBACK
2903 	gl.debugMessageCallback(debug_proc, &m_context);
2904 	GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
2905 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
2906 
2907 	GLuint invalid_id   = 1; /* Start with 1, as 0 is not valid name */
2908 	GLint  max_samplers = 0;
2909 
2910 	/* Get max */
2911 	gl.getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_samplers);
2912 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2913 
2914 	/* Storage */
2915 	std::vector<GLuint> sampler_ids;
2916 	std::vector<GLuint> t_sampler_ids;
2917 
2918 	sampler_ids.resize(max_samplers);
2919 	t_sampler_ids.resize(max_samplers);
2920 
2921 	for (GLint i = 0; i < max_samplers; ++i)
2922 	{
2923 		t_sampler_ids[i] = 0;
2924 	}
2925 
2926 	/* Prepare samplers */
2927 	gl.genSamplers(max_samplers, &sampler_ids[0]);
2928 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenSamplers");
2929 
2930 	try
2931 	{
2932 		/* - execute BindSamplers to bind all samplers;
2933 		 * - inspect bindings to verify that proper samplers were set;
2934 		 */
2935 		gl.bindSamplers(0 /* first */, max_samplers /* count */, &sampler_ids[0]);
2936 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindSamplers");
2937 
2938 		for (GLint i = 0; i < max_samplers; ++i)
2939 		{
2940 			checkBinding(m_context, GL_SAMPLER_BINDING, i, "Sampler", sampler_ids[i]);
2941 		}
2942 
2943 		/* - execute BindSamplers for first half of bindings with <samplers> filled
2944 		 * with zeros, to unbind those samplers;
2945 		 * - inspect bindings to verify that proper samplers were unbound;
2946 		 */
2947 		GLint half_index = max_samplers / 2;
2948 
2949 		gl.bindSamplers(0, half_index, &t_sampler_ids[0]);
2950 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindSamplers");
2951 
2952 		for (GLint i = 0; i < half_index; ++i)
2953 		{
2954 			checkBinding(m_context, GL_SAMPLER_BINDING, i, "Sampler", 0);
2955 		}
2956 
2957 		for (GLint i = half_index; i < max_samplers; ++i)
2958 		{
2959 			checkBinding(m_context, GL_SAMPLER_BINDING, i, "Sampler", sampler_ids[i]);
2960 		}
2961 
2962 		/* - execute BindSamplers for second half of bindings with NULL as <samplers>,
2963 		 * to unbind those samplers;
2964 		 * - inspect bindings to verify that proper samplers were unbound;
2965 		 */
2966 		gl.bindSamplers(half_index, max_samplers - half_index, 0);
2967 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindSamplers");
2968 
2969 		for (GLint i = 0; i < max_samplers; ++i)
2970 		{
2971 			checkBinding(m_context, GL_SAMPLER_BINDING, i, "Sampler", 0);
2972 		}
2973 
2974 		/* - modify <samplers> so first entry is invalid;
2975 		 * - execute BindSamplers to bind all samplers; It is expected that
2976 		 * INVALID_OPERATION will be generated;
2977 		 * - inspect bindings to verify that proper samplers were set;
2978 		 */
2979 
2980 		/* Find invalid id */
2981 		while (1)
2982 		{
2983 			if (GL_TRUE != gl.isSampler(invalid_id))
2984 			{
2985 				break;
2986 			}
2987 
2988 			invalid_id += 1;
2989 		}
2990 
2991 		/* Prepare ids */
2992 		t_sampler_ids[0] = invalid_id;
2993 
2994 		for (GLint i = 1; i < max_samplers; ++i)
2995 		{
2996 			t_sampler_ids[i] = sampler_ids[i];
2997 		}
2998 
2999 		/* Bind */
3000 		gl.bindSamplers(0, max_samplers, &t_sampler_ids[0]);
3001 		CHECK_ERROR(GL_INVALID_OPERATION, "BindSamplers with invalid sampler id");
3002 
3003 		/* Set 0 for invalid entry */
3004 		t_sampler_ids[0] = 0;
3005 
3006 		for (GLint i = 0; i < max_samplers; ++i)
3007 		{
3008 			checkBinding(m_context, GL_SAMPLER_BINDING, i, "Sampler", t_sampler_ids[i]);
3009 		}
3010 
3011 		/* - unbind all samplers. */
3012 		gl.bindSamplers(0, max_samplers, 0);
3013 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindSamplers");
3014 	}
3015 	catch (const std::exception&)
3016 	{
3017 		gl.deleteSamplers(max_samplers, &sampler_ids[0]);
3018 
3019 		TCU_FAIL("Invalid error generated");
3020 	}
3021 
3022 	/* Delete samplers */
3023 	gl.deleteSamplers(max_samplers, &sampler_ids[0]);
3024 
3025 	/* Set result */
3026 	m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3027 
3028 	/* Done */
3029 	return tcu::TestNode::STOP;
3030 }
3031 
3032 /** Constructor
3033  *
3034  * @param context Test context
3035  **/
FunctionalBindImageTexturesTest(deqp::Context & context)3036 FunctionalBindImageTexturesTest::FunctionalBindImageTexturesTest(deqp::Context& context)
3037 	: TestCase(context, "functional_bind_image_textures", "Verifies that BindImageTextures works as expected")
3038 {
3039 	/* Nothing to be done */
3040 }
3041 
3042 /** Execute test
3043  *
3044  * @return tcu::TestNode::STOP
3045  **/
iterate()3046 tcu::TestNode::IterateResult FunctionalBindImageTexturesTest::iterate()
3047 {
3048 	static const GLuint depth  = 6;
3049 	static const GLuint height = 6;
3050 	static const GLuint width  = 6;
3051 
3052 	const Functions& gl = m_context.getRenderContext().getFunctions();
3053 
3054 #if DEBUG_ENBALE_MESSAGE_CALLBACK
3055 	gl.debugMessageCallback(debug_proc, &m_context);
3056 	GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
3057 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
3058 
3059 	GLuint invalid_id   = 1; /* Start with 1, as 0 is not valid name */
3060 	GLint  max_textures = 0;
3061 
3062 	/* Get max */
3063 	gl.getIntegerv(GL_MAX_IMAGE_UNITS, &max_textures);
3064 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3065 
3066 	/* Storage */
3067 	Buffer				 buffer;
3068 	std::vector<Texture> texture;
3069 	std::vector<GLuint>  texture_ids;
3070 	std::vector<GLuint>  t_texture_ids;
3071 
3072 	texture.resize(max_textures);
3073 	texture_ids.resize(max_textures);
3074 	t_texture_ids.resize(max_textures);
3075 
3076 	/* Prepare buffer */
3077 	buffer.InitData(m_context, GL_TEXTURE_BUFFER, GL_DYNAMIC_COPY, 16 /* size */, 0 /* data */);
3078 
3079 	/* Prepare textures */
3080 	for (GLint i = 0; i < (GLint)s_n_texture_tragets; ++i)
3081 	{
3082 		const GLenum target = s_texture_infos[i].m_target;
3083 
3084 		if (i >= max_textures)
3085 		{
3086 			break;
3087 		}
3088 
3089 		if (GL_TEXTURE_BUFFER != target)
3090 		{
3091 			texture[i].InitStorage(m_context, target, 1, GL_RGBA8, width, height, depth);
3092 		}
3093 		else
3094 		{
3095 			texture[i].InitBuffer(m_context, GL_RGBA8, buffer.m_id);
3096 		}
3097 
3098 		/* Unbind */
3099 		Texture::Bind(gl, 0, target);
3100 	}
3101 
3102 	for (GLint i = (GLint)s_n_texture_tragets; i < max_textures; ++i)
3103 	{
3104 		texture[i].InitStorage(m_context, GL_TEXTURE_2D, 1, GL_RGBA8, width, height, depth);
3105 	}
3106 
3107 	/* Unbind */
3108 	Texture::Bind(gl, 0, GL_TEXTURE_2D);
3109 
3110 	for (GLint i = 0; i < max_textures; ++i)
3111 	{
3112 		texture_ids[i] = texture[i].m_id;
3113 	}
3114 
3115 	/*
3116 	 * - execute BindImageTextures to bind all images;
3117 	 * - inspect bindings to verify that proper images were set;
3118 	 */
3119 	gl.bindImageTextures(0, max_textures, &texture_ids[0]);
3120 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTextures");
3121 
3122 	for (GLint i = 0; i < max_textures; ++i)
3123 	{
3124 		checkBinding(m_context, GL_IMAGE_BINDING_NAME, i, "Image unit", texture_ids[i]);
3125 	}
3126 
3127 	/*
3128 	 * - execute BindTextures for the first half of units with <textures> filled
3129 	 * with zeros, to unbind those units;
3130 	 * - inspect bindings of all texture units to verify that proper bindings were
3131 	 * unbound;
3132 	 */
3133 	GLint half_index = max_textures / 2;
3134 
3135 	for (GLint i = 0; i < max_textures; ++i)
3136 	{
3137 		t_texture_ids[i] = 0;
3138 	}
3139 
3140 	gl.bindImageTextures(0, half_index, &t_texture_ids[0]);
3141 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTextures");
3142 
3143 	for (GLint i = 0; i < half_index; ++i)
3144 	{
3145 		checkBinding(m_context, GL_IMAGE_BINDING_NAME, i, "Image unit", 0);
3146 	}
3147 
3148 	for (GLint i = half_index; i < max_textures; ++i)
3149 	{
3150 		checkBinding(m_context, GL_IMAGE_BINDING_NAME, i, "Image unit", texture_ids[i]);
3151 	}
3152 
3153 	/*
3154 	 * - execute BindTextures for the second half of units with NULL as<textures>,
3155 	 * to unbind those units;
3156 	 * - inspect bindings of all texture units to verify that proper bindings were
3157 	 * unbound;
3158 	 */
3159 	gl.bindImageTextures(half_index, max_textures - half_index, 0);
3160 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTextures");
3161 
3162 	for (GLint i = 0; i < max_textures; ++i)
3163 	{
3164 		checkBinding(m_context, GL_IMAGE_BINDING_NAME, i, "Image unit", 0);
3165 	}
3166 
3167 	/*
3168 	 * - modify <textures> so first entry is invalid;
3169 	 * - execute BindTextures to bind all textures; It is expected that
3170 	 * INVALID_OPERATION will be generated;
3171 	 * - inspect bindings of all texture units to verify that proper bindings were
3172 	 * set;
3173 	 */
3174 
3175 	/* Find invalid id */
3176 	while (1)
3177 	{
3178 		if (GL_TRUE != gl.isTexture(invalid_id))
3179 		{
3180 			break;
3181 		}
3182 
3183 		invalid_id += 1;
3184 	}
3185 
3186 	/* Set invalid id */
3187 	texture_ids[0] = invalid_id;
3188 
3189 	gl.bindImageTextures(0, max_textures, &texture_ids[0]);
3190 	CHECK_ERROR(GL_INVALID_OPERATION, "BindImageTextures with invalid texture id");
3191 
3192 	checkBinding(m_context, GL_IMAGE_BINDING_NAME, 0, "Image unit", 0);
3193 	for (GLint i = 1; i < max_textures; ++i)
3194 	{
3195 		checkBinding(m_context, GL_IMAGE_BINDING_NAME, i, "Image unit", texture_ids[i]);
3196 	}
3197 
3198 	/* - unbind all textures. */
3199 	gl.bindImageTextures(0, max_textures, 0);
3200 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTextures");
3201 
3202 	/* Set result */
3203 	m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3204 
3205 	/* Done */
3206 	return tcu::TestNode::STOP;
3207 }
3208 
3209 /** Constructor
3210  *
3211  * @param context Test context
3212  **/
FunctionalBindVertexBuffersTest(deqp::Context & context)3213 FunctionalBindVertexBuffersTest::FunctionalBindVertexBuffersTest(deqp::Context& context)
3214 	: TestCase(context, "functional_bind_vertex_buffers", "Verifies that BindVertexBuffers works as expected")
3215 {
3216 	/* Nothing to be done */
3217 }
3218 
3219 /** Execute test
3220  *
3221  * @return tcu::TestNode::STOP
3222  **/
iterate()3223 tcu::TestNode::IterateResult FunctionalBindVertexBuffersTest::iterate()
3224 {
3225 	const Functions& gl = m_context.getRenderContext().getFunctions();
3226 
3227 #if DEBUG_ENBALE_MESSAGE_CALLBACK
3228 	gl.debugMessageCallback(debug_proc, &m_context);
3229 	GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
3230 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
3231 
3232 	static const GLintptr buffer_size = 16;
3233 	static const GLintptr offset	  = 4;
3234 	static const GLsizei  stride	  = 4;
3235 
3236 	GLuint invalid_id  = 1; /* Start with 1, as 0 is not valid name */
3237 	GLint  max_buffers = 0;
3238 
3239 	/* Get max */
3240 	gl.getIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &max_buffers);
3241 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3242 
3243 	/* Storage */
3244 	std::vector<Buffer>   buffer;
3245 	std::vector<GLuint>   buffer_ids;
3246 	std::vector<GLintptr> offsets;
3247 	std::vector<GLsizei>  strides;
3248 	std::vector<GLuint>   t_buffer_ids;
3249 
3250 	buffer.resize(max_buffers);
3251 	buffer_ids.resize(max_buffers);
3252 	offsets.resize(max_buffers);
3253 	strides.resize(max_buffers);
3254 	t_buffer_ids.resize(max_buffers);
3255 
3256 	/* Prepare buffers */
3257 	for (GLint i = 0; i < max_buffers; ++i)
3258 	{
3259 		buffer[i].InitData(m_context, GL_ARRAY_BUFFER, GL_DYNAMIC_COPY, buffer_size, 0 /* data */);
3260 
3261 		buffer_ids[i]   = buffer[i].m_id;
3262 		offsets[i]		= offset;
3263 		strides[i]		= stride;
3264 		t_buffer_ids[i] = 0;
3265 	}
3266 
3267 	GLuint vao = 0;
3268 	gl.genVertexArrays(1, &vao);
3269 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
3270 	try
3271 	{
3272 		gl.bindVertexArray(vao);
3273 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArrays");
3274 
3275 		/* - execute BindVertexBuffers to bind all buffer;
3276 		 * - inspect bindings to verify that proper buffers were set;
3277 		 */
3278 		gl.bindVertexBuffers(0, max_buffers, &buffer_ids[0], &offsets[0], &strides[0]);
3279 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexBuffers");
3280 
3281 		for (GLint i = 0; i < max_buffers; ++i)
3282 		{
3283 			checkVertexAttribBinding(m_context, i, buffer_ids[i]);
3284 		}
3285 
3286 		/* - execute BindVertexBuffers for first half of bindings with <buffers> filled
3287 		 * with zeros, to unbind those buffers;
3288 		 * - inspect bindings to verify that proper buffers were unbound;
3289 		 */
3290 		GLint half_index = max_buffers / 2;
3291 
3292 		gl.bindVertexBuffers(0, half_index, &t_buffer_ids[0], &offsets[0], &strides[0]);
3293 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexBuffers");
3294 
3295 		for (GLint i = 0; i < half_index; ++i)
3296 		{
3297 			checkVertexAttribBinding(m_context, i, 0);
3298 		}
3299 
3300 		for (GLint i = half_index; i < max_buffers; ++i)
3301 		{
3302 			checkVertexAttribBinding(m_context, i, buffer_ids[i]);
3303 		}
3304 
3305 		/* - execute BindVertexBuffers for second half of bindings with NULL as
3306 		 * <buffers>, to unbind those buffers;
3307 		 * - inspect bindings to verify that proper buffers were unbound;
3308 		 */
3309 		gl.bindVertexBuffers(half_index, max_buffers - half_index, 0, &offsets[0], &strides[0]);
3310 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexBuffers");
3311 
3312 		for (GLint i = 0; i < max_buffers; ++i)
3313 		{
3314 			checkVertexAttribBinding(m_context, i, 0);
3315 		}
3316 
3317 		/* - modify <buffers> so first entry is invalid;
3318 		 * - execute BindVertexBuffers to bind all buffers; It is expected that
3319 		 * INVALID_OPERATION will be generated;
3320 		 * - inspect bindings to verify that proper buffers were set;
3321 		 */
3322 
3323 		/* Find invalid id */
3324 		while (1)
3325 		{
3326 			if (GL_TRUE != gl.isBuffer(invalid_id))
3327 			{
3328 				break;
3329 			}
3330 
3331 			invalid_id += 1;
3332 		}
3333 
3334 		buffer_ids[0] = invalid_id;
3335 		gl.bindVertexBuffers(0, max_buffers, &buffer_ids[0], &offsets[0], &strides[0]);
3336 		CHECK_ERROR(GL_INVALID_OPERATION, "BindVertexBuffers with invalid id");
3337 
3338 		checkVertexAttribBinding(m_context, 0, 0);
3339 		for (GLint i = 1; i < max_buffers; ++i)
3340 		{
3341 			checkVertexAttribBinding(m_context, i, buffer_ids[i]);
3342 		}
3343 
3344 		/* - unbind all buffers. */
3345 		gl.bindVertexBuffers(0, max_buffers, 0, &offsets[0], &strides[0]);
3346 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexBuffers");
3347 	}
3348 	catch (const std::exception&)
3349 	{
3350 		gl.deleteVertexArrays(1, &vao);
3351 
3352 		TCU_FAIL("Unexpected error generated");
3353 	}
3354 
3355 	gl.deleteVertexArrays(1, &vao);
3356 	GLU_EXPECT_NO_ERROR(gl.getError(), "DeleteVertexArrays");
3357 
3358 	/* Set result */
3359 	m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3360 
3361 	/* Done */
3362 	return tcu::TestNode::STOP;
3363 }
3364 
3365 /** Constructor
3366  *
3367  * @param context Test context
3368  **/
DispatchBindBuffersBaseTest(deqp::Context & context)3369 DispatchBindBuffersBaseTest::DispatchBindBuffersBaseTest(deqp::Context& context)
3370 	: TestCase(context, "dispatch_bind_buffers_base", "Tests BindBuffersBase with dispatch command")
3371 {
3372 	/* Nothing to be done */
3373 }
3374 
3375 /** Execute test
3376  *
3377  * @return tcu::TestNode::STOP
3378  **/
iterate()3379 tcu::TestNode::IterateResult DispatchBindBuffersBaseTest::iterate()
3380 {
3381 	static const GLchar* cs = "#version 440 core\n"
3382 							  "\n"
3383 							  "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
3384 							  "\n"
3385 							  "UBO_LIST\n"
3386 							  "layout (std140, binding = 0) buffer SSB {\n"
3387 							  "    vec4 sum;\n"
3388 							  "} ssb;\n"
3389 							  "\n"
3390 							  "void main()\n"
3391 							  "{\n"
3392 							  "    ssb.sum = SUM_LIST;\n"
3393 							  "}\n"
3394 							  "\n";
3395 
3396 	static const GLchar* ubo = "layout (std140, binding = XXX) uniform BXXX { vec4 data; } bXXX;";
3397 
3398 	static const GLintptr buffer_size = 4 * sizeof(GLfloat);
3399 
3400 	const Functions& gl = m_context.getRenderContext().getFunctions();
3401 
3402 	bool test_result = true;
3403 
3404 #if DEBUG_ENBALE_MESSAGE_CALLBACK
3405 	gl.debugMessageCallback(debug_proc, &m_context);
3406 	GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
3407 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
3408 
3409 	GLint   max_buffers = 0;
3410 	GLfloat sum[4]		= { 0.0f, 0.0f, 0.0f, 0.0f };
3411 
3412 	/* Get max */
3413 	gl.getIntegerv(GL_MAX_COMPUTE_UNIFORM_BLOCKS, &max_buffers);
3414 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3415 
3416 	/* UBO */
3417 	/* Storage */
3418 	std::vector<Buffer> uni_buffer;
3419 	std::vector<GLuint> uni_buffer_ids;
3420 
3421 	uni_buffer.resize(max_buffers);
3422 	uni_buffer_ids.resize(max_buffers);
3423 
3424 	/* Prepare buffers */
3425 	for (GLint i = 0; i < max_buffers; ++i)
3426 	{
3427 		const GLfloat data[4] = {
3428 			(GLfloat)(i * 4 + 0), (GLfloat)(i * 4 + 1), (GLfloat)(i * 4 + 2), (GLfloat)(i * 4 + 3),
3429 		};
3430 
3431 		sum[0] += data[0];
3432 		sum[1] += data[1];
3433 		sum[2] += data[2];
3434 		sum[3] += data[3];
3435 
3436 		uni_buffer[i].InitData(m_context, GL_UNIFORM_BUFFER, GL_DYNAMIC_COPY, buffer_size, data);
3437 
3438 		uni_buffer_ids[i] = uni_buffer[i].m_id;
3439 	}
3440 
3441 	gl.bindBuffersBase(GL_UNIFORM_BUFFER, 0 /* first */, max_buffers /* count */, &uni_buffer_ids[0]);
3442 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersBase");
3443 
3444 	/* SSBO */
3445 	Buffer ssb_buffer;
3446 	ssb_buffer.InitData(m_context, GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, buffer_size, 0 /* data */);
3447 
3448 	ssb_buffer.BindBase(0);
3449 
3450 	/* Prepare program */
3451 	size_t		ubo_position = 0;
3452 	size_t		sum_position = 0;
3453 	std::string cs_source	= cs;
3454 	for (GLint i = 0; i < max_buffers; ++i)
3455 	{
3456 		size_t ubo_start_position = ubo_position;
3457 		size_t sum_start_position = sum_position;
3458 
3459 		GLchar index[16];
3460 
3461 		sprintf(index, "%d", i);
3462 
3463 		/* Add entry to ubo list */
3464 		replaceToken("UBO_LIST", ubo_position, "UBO\nUBO_LIST", cs_source);
3465 		ubo_position = ubo_start_position;
3466 
3467 		replaceToken("UBO", ubo_position, ubo, cs_source);
3468 		ubo_position = ubo_start_position;
3469 
3470 		replaceToken("XXX", ubo_position, index, cs_source);
3471 		replaceToken("XXX", ubo_position, index, cs_source);
3472 		replaceToken("XXX", ubo_position, index, cs_source);
3473 
3474 		/* Add entry to sum list */
3475 		replaceToken("SUM_LIST", sum_position, "bXXX.data + SUM_LIST", cs_source);
3476 		sum_position = sum_start_position;
3477 
3478 		replaceToken("XXX", sum_position, index, cs_source);
3479 	}
3480 
3481 	/* Remove token for lists */
3482 	replaceToken(" + SUM_LIST", sum_position, "", cs_source);
3483 	replaceToken("UBO_LIST", ubo_position, "", cs_source);
3484 
3485 	Program program(m_context);
3486 	program.Init(cs_source.c_str(), "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
3487 
3488 	program.Use();
3489 
3490 	gl.dispatchCompute(1, 1, 1);
3491 	GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
3492 
3493 	gl.memoryBarrier(GL_ALL_BARRIER_BITS);
3494 	GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3495 
3496 	GLfloat* result = (GLfloat*)gl.mapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY);
3497 	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
3498 
3499 	if (0 != memcmp(result, sum, 4 * sizeof(GLfloat)))
3500 	{
3501 		test_result = false;
3502 	}
3503 
3504 	gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
3505 	gl.getError(); /* Ignore error */
3506 
3507 	/* Set result */
3508 	if (true == test_result)
3509 	{
3510 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3511 	}
3512 	else
3513 	{
3514 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3515 	}
3516 
3517 	/* Done */
3518 	return tcu::TestNode::STOP;
3519 }
3520 
3521 /** Constructor
3522  *
3523  * @param context Test context
3524  **/
DispatchBindBuffersRangeTest(deqp::Context & context)3525 DispatchBindBuffersRangeTest::DispatchBindBuffersRangeTest(deqp::Context& context)
3526 	: TestCase(context, "dispatch_bind_buffers_range", "Tests BindBuffersRange with dispatch command")
3527 {
3528 	/* Nothing to be done */
3529 }
3530 
3531 /** Execute test
3532  *
3533  * @return tcu::TestNode::STOP
3534  **/
iterate()3535 tcu::TestNode::IterateResult DispatchBindBuffersRangeTest::iterate()
3536 {
3537 	static const GLchar* cs = "#version 440 core\n"
3538 							  "\n"
3539 							  "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
3540 							  "\n"
3541 							  "layout (std140, binding = 0) uniform B0 { int data; } b0;"
3542 							  "layout (std140, binding = 1) uniform B1 { int data; } b1;"
3543 							  "layout (std140, binding = 2) uniform B2 { int data; } b2;"
3544 							  "layout (std140, binding = 3) uniform B3 { int data; } b3;"
3545 							  "\n"
3546 							  "layout (std140, binding = 0) buffer SSB {\n"
3547 							  "    int sum;\n"
3548 							  "} ssb;\n"
3549 							  "\n"
3550 							  "void main()\n"
3551 							  "{\n"
3552 							  "    //ssb.sum = b1.data;// + b1.data + b2.data + b3.data;\n"
3553 							  "    ssb.sum = b0.data + b1.data + b2.data + b3.data;\n"
3554 							  "}\n"
3555 							  "\n";
3556 
3557 	static const GLint  data[]	= { 0x00010001, 0x01000100 };
3558 	static const size_t n_buffers = 4;
3559 	static const GLint  sum		  = 0x02020202;
3560 
3561 	const Functions& gl = m_context.getRenderContext().getFunctions();
3562 
3563 	bool test_result = true;
3564 
3565 #if DEBUG_ENBALE_MESSAGE_CALLBACK
3566 	gl.debugMessageCallback(debug_proc, &m_context);
3567 	GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
3568 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
3569 
3570 	/* UBO */
3571 	GLint offset_alignment = 0;
3572 
3573 	gl.getIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &offset_alignment);
3574 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3575 
3576 	/* Storage */
3577 	Buffer				 uni_buffer;
3578 	GLuint				 uni_buffer_ids[n_buffers];
3579 	std::vector<GLubyte> uni_data;
3580 	GLintptr			 uni_offsets[n_buffers];
3581 	GLintptr			 uni_sizes[n_buffers];
3582 
3583 	const size_t buffer_size = (n_buffers - 1) * offset_alignment + sizeof(GLint);
3584 	uni_data.resize(buffer_size);
3585 
3586 	for (size_t i = 0; i < buffer_size; ++i)
3587 	{
3588 		uni_data[i] = 0xaa;
3589 	}
3590 
3591 	for (size_t i = 0; i < n_buffers; ++i)
3592 	{
3593 		void*		dst = &uni_data[i * offset_alignment];
3594 		const void* src = &data[(i % 2)];
3595 
3596 		memcpy(dst, src, sizeof(GLint));
3597 	}
3598 
3599 	uni_buffer.InitData(m_context, GL_UNIFORM_BUFFER, GL_DYNAMIC_COPY, buffer_size, &uni_data[0]);
3600 
3601 	for (size_t i = 0; i < n_buffers; ++i)
3602 	{
3603 		uni_buffer_ids[i] = uni_buffer.m_id;
3604 		uni_offsets[i]	= i * offset_alignment;
3605 		uni_sizes[i]	  = sizeof(GLint);
3606 	}
3607 
3608 	gl.bindBuffersRange(GL_UNIFORM_BUFFER, 0 /* first */, n_buffers /* count */, &uni_buffer_ids[0], &uni_offsets[0],
3609 						&uni_sizes[0]);
3610 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersRange");
3611 
3612 	/* SSBO */
3613 	Buffer ssb_buffer;
3614 	ssb_buffer.InitData(m_context, GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, sizeof(GLint), 0 /* data */);
3615 
3616 	ssb_buffer.BindBase(0);
3617 
3618 	/* Prepare program */
3619 	Program program(m_context);
3620 	program.Init(cs, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
3621 
3622 	program.Use();
3623 
3624 	gl.dispatchCompute(1, 1, 1);
3625 	GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
3626 
3627 	gl.memoryBarrier(GL_ALL_BARRIER_BITS);
3628 	GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3629 
3630 	GLint* result = (GLint*)gl.mapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY);
3631 	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
3632 
3633 	if (0 != memcmp(result, &sum, sizeof(sum)))
3634 	{
3635 		test_result = false;
3636 	}
3637 
3638 	gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
3639 	gl.getError(); /* Ignore error */
3640 
3641 	/* Set result */
3642 	if (true == test_result)
3643 	{
3644 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3645 	}
3646 	else
3647 	{
3648 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3649 	}
3650 
3651 	/* Done */
3652 	return tcu::TestNode::STOP;
3653 }
3654 
3655 /** Constructor
3656  *
3657  * @param context Test context
3658  **/
DispatchBindTexturesTest(deqp::Context & context)3659 DispatchBindTexturesTest::DispatchBindTexturesTest(deqp::Context& context)
3660 	: TestCase(context, "dispatch_bind_textures", "Tests BindTextures with dispatch command")
3661 {
3662 	/* Nothing to be done */
3663 }
3664 
3665 /** Execute test
3666  *
3667  * @return tcu::TestNode::STOP
3668  **/
iterate()3669 tcu::TestNode::IterateResult DispatchBindTexturesTest::iterate()
3670 {
3671 	static const GLchar* cs = "#version 440 core\n"
3672 							  "\n"
3673 							  "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
3674 							  "\n"
3675 							  "SAMPLER_LIST\n"
3676 							  "layout (std140, binding = 0) buffer SSB {\n"
3677 							  "    uint sum;\n"
3678 							  "} ssb;\n"
3679 							  "\n"
3680 							  "void main()\n"
3681 							  "{\n"
3682 							  "    uvec4 sum = SUM_LIST;\n"
3683 							  "    ssb.sum = sum.r\n;"
3684 							  "}\n"
3685 							  "\n";
3686 
3687 	static const GLchar* sampler = "layout (location = XXX) uniform SAMPLER sXXX;";
3688 
3689 	static const GLchar* sampling[] = {
3690 		"texture(sXXX, COORDS)", "texture(sXXX, COORDS)",		"texture(sXXX, COORDS)",	  "texture(sXXX, COORDS)",
3691 		"texture(sXXX, COORDS)", "texelFetch(sXXX, COORDS)",	"texture(sXXX, COORDS)",	  "texture(sXXX, COORDS)",
3692 		"texture(sXXX, COORDS)", "texelFetch(sXXX, COORDS, 0)", "texelFetch(sXXX, COORDS, 0)"
3693 	};
3694 
3695 	static const GLchar* samplers[] = { "usampler1D",	 "usampler1DArray", "usampler2D",		 "usampler2DArray",
3696 										"usampler3D",	 "usamplerBuffer",  "usamplerCube",	 "usamplerCubeArray",
3697 										"usampler2DRect", "usampler2DMS",	"usampler2DMSArray" };
3698 
3699 	static const GLchar* coordinates[] = {
3700 		"0.5f",
3701 		"vec2(0.5f, 0.0f)",
3702 		"vec2(0.5f, 0.5f)",
3703 		"vec3(0.5f, 0.5f, 0.0f)",
3704 		"vec3(0.5f, 0.5f, 0.5f)",
3705 		"0",
3706 		"vec3(0.5f, 0.5f, 0.5f)",
3707 		"vec4(0.5f, 0.5f, 0.5f, 0.0f)",
3708 		"vec2(0.5f, 0.5f)",
3709 		"ivec2(0, 0)",
3710 		"ivec3(0, 0, 0)",
3711 	};
3712 
3713 	static const GLuint depth  = 6;
3714 	static const GLuint height = 6;
3715 	static const GLuint width  = 6;
3716 
3717 	const Functions& gl = m_context.getRenderContext().getFunctions();
3718 
3719 	bool test_result = true;
3720 
3721 #if DEBUG_ENBALE_MESSAGE_CALLBACK
3722 	gl.debugMessageCallback(debug_proc, &m_context);
3723 	GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
3724 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
3725 
3726 	GLint  max_textures		 = 0;
3727 	GLint  max_image_samples = 0;
3728 	GLuint sum				 = 0;
3729 
3730 	/* Get max */
3731 	gl.getIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &max_textures);
3732 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3733 
3734 	/* Check if load/store from multisampled images is supported */
3735 	gl.getIntegerv(GL_MAX_IMAGE_SAMPLES, &max_image_samples);
3736 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3737 
3738 	/* Textures */
3739 	/* Storage */
3740 	std::vector<Texture> texture;
3741 	std::vector<GLuint>  texture_ids;
3742 	Buffer				 texture_buffer;
3743 
3744 	texture.resize(max_textures);
3745 	texture_ids.resize(max_textures);
3746 
3747 	/* Prepare */
3748 	for (GLint i = 0; i < max_textures; ++i)
3749 	{
3750 		GLenum target = getTarget(i);
3751 		if (target >= GL_TEXTURE_2D_MULTISAMPLE && max_image_samples == 0)
3752 			target = GL_TEXTURE_2D;
3753 
3754 		GLuint data[width * height * depth];
3755 
3756 		for (GLuint j = 0; j < width * height * depth; ++j)
3757 		{
3758 			data[j] = i;
3759 		}
3760 
3761 		sum += i;
3762 
3763 		bool is_array = false;
3764 
3765 		switch (target)
3766 		{
3767 		case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
3768 			is_array = true;
3769 		/* Intentional fallthrough */
3770 
3771 		case GL_TEXTURE_2D_MULTISAMPLE:
3772 			texture[i].InitStorage(m_context, target, 1, GL_R32UI, width, height, depth);
3773 			fillMSTexture(m_context, texture[i].m_id, i, is_array);
3774 			break;
3775 
3776 		case GL_TEXTURE_BUFFER:
3777 			texture_buffer.InitData(m_context, GL_TEXTURE_BUFFER, GL_DYNAMIC_COPY, sizeof(data), data);
3778 			texture[i].InitBuffer(m_context, GL_R32UI, texture_buffer.m_id);
3779 			break;
3780 
3781 		default:
3782 			texture[i].InitStorage(m_context, target, 1, GL_R32UI, width, height, depth);
3783 			Texture::Bind(gl, texture[i].m_id, target);
3784 			Texture::SubImage(gl, target, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height, depth,
3785 							  GL_RED_INTEGER, GL_UNSIGNED_INT, &data);
3786 			gl.texParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3787 			gl.texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3788 			break;
3789 		}
3790 
3791 		/* Clean */
3792 		Texture::Bind(gl, 0, target);
3793 
3794 		texture_ids[i] = texture[i].m_id;
3795 	}
3796 
3797 	gl.bindTextures(0 /* first */, max_textures /* count */, &texture_ids[0]);
3798 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindTextures");
3799 
3800 	/* SSBO */
3801 	Buffer ssb_buffer;
3802 	ssb_buffer.InitData(m_context, GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, sizeof(GLuint), 0 /* data */);
3803 
3804 	ssb_buffer.BindBase(0);
3805 
3806 	/* Prepare program */
3807 	size_t		sam_position	 = 0;
3808 	size_t		sum_position	 = 0;
3809 	std::string cs_source		 = cs;
3810 	GLint		max_target_index = (GLint)(max_image_samples > 0 ? s_n_texture_tragets : s_n_texture_tragets - 2);
3811 	for (GLint i = 0; i < max_textures; ++i)
3812 	{
3813 		size_t sam_start_position = sam_position;
3814 		size_t sum_start_position = sum_position;
3815 
3816 		GLchar index[16];
3817 
3818 		sprintf(index, "%d", i);
3819 
3820 		const GLchar* coords		= 0;
3821 		const GLchar* sampler_type  = 0;
3822 		const GLchar* sampling_code = 0;
3823 
3824 		if (i < max_target_index)
3825 		{
3826 			coords		  = coordinates[i];
3827 			sampler_type  = samplers[i];
3828 			sampling_code = sampling[i];
3829 		}
3830 		else
3831 		{
3832 			coords		  = coordinates[2]; /* vec2(0.5f, 0.5f) */
3833 			sampler_type  = samplers[2];	/* usampler2D */
3834 			sampling_code = sampling[2];	/* texture(sXXX, COORDS) */
3835 		}
3836 
3837 		/* Add entry to ubo list */
3838 		replaceToken("SAMPLER_LIST", sam_position, "SAMPLER\nSAMPLER_LIST", cs_source);
3839 		sam_position = sam_start_position;
3840 
3841 		replaceToken("SAMPLER", sam_position, sampler, cs_source);
3842 		sam_position = sam_start_position;
3843 
3844 		replaceToken("XXX", sam_position, index, cs_source);
3845 		replaceToken("SAMPLER", sam_position, sampler_type, cs_source);
3846 		replaceToken("XXX", sam_position, index, cs_source);
3847 
3848 		/* Add entry to sum list */
3849 		replaceToken("SUM_LIST", sum_position, "SAMPLING + SUM_LIST", cs_source);
3850 		sum_position = sum_start_position;
3851 
3852 		replaceToken("SAMPLING", sum_position, sampling_code, cs_source);
3853 		sum_position = sum_start_position;
3854 
3855 		replaceToken("XXX", sum_position, index, cs_source);
3856 		replaceToken("COORDS", sum_position, coords, cs_source);
3857 	}
3858 
3859 	/* Remove token for lists */
3860 	replaceToken(" + SUM_LIST", sum_position, "", cs_source);
3861 	replaceToken("SAMPLER_LIST", sam_position, "", cs_source);
3862 
3863 	Program program(m_context);
3864 	program.Init(cs_source.c_str(), "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
3865 
3866 	program.Use();
3867 
3868 	/* Set samplers */
3869 	for (GLint i = 0; i < max_textures; ++i)
3870 	{
3871 		gl.uniform1i(i, i);
3872 		GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
3873 	}
3874 
3875 	gl.dispatchCompute(1, 1, 1);
3876 	GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
3877 
3878 	gl.memoryBarrier(GL_ALL_BARRIER_BITS);
3879 	GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3880 
3881 	GLuint* result = (GLuint*)gl.mapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY);
3882 	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
3883 
3884 	if (0 != memcmp(result, &sum, sizeof(sum)))
3885 	{
3886 		test_result = false;
3887 	}
3888 
3889 	gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
3890 	gl.getError(); /* Ignore error */
3891 
3892 	/* Set result */
3893 	if (true == test_result)
3894 	{
3895 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3896 	}
3897 	else
3898 	{
3899 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3900 	}
3901 
3902 	/* Done */
3903 	return tcu::TestNode::STOP;
3904 }
3905 
3906 /** Constructor
3907  *
3908  * @param context Test context
3909  **/
DispatchBindImageTexturesTest(deqp::Context & context)3910 DispatchBindImageTexturesTest::DispatchBindImageTexturesTest(deqp::Context& context)
3911 	: TestCase(context, "dispatch_bind_image_textures", "Tests BindImageTextures with dispatch command")
3912 {
3913 	/* Nothing to be done */
3914 }
3915 
3916 /** Execute test
3917  *
3918  * @return tcu::TestNode::STOP
3919  **/
iterate()3920 tcu::TestNode::IterateResult DispatchBindImageTexturesTest::iterate()
3921 {
3922 	static const GLchar* cs = "#version 440 core\n"
3923 							  "\n"
3924 							  "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
3925 							  "\n"
3926 							  "IMAGE_LIST\n"
3927 							  "layout (std140, binding = 0) buffer SSB {\n"
3928 							  "    uint sum;\n"
3929 							  "} ssb;\n"
3930 							  "\n"
3931 							  "void main()\n"
3932 							  "{\n"
3933 							  "    uvec4 sum = SUM_LIST;\n"
3934 							  "    ssb.sum = sum.r\n;"
3935 							  "}\n"
3936 							  "\n";
3937 
3938 	static const GLchar* image = "layout (location = XXX, r32ui) readonly uniform IMAGE iXXX;";
3939 
3940 	static const GLchar* loading[] = {
3941 		"imageLoad(iXXX, COORDS)", "imageLoad(iXXX, COORDS)",	"imageLoad(iXXX, COORDS)",   "imageLoad(iXXX, COORDS)",
3942 		"imageLoad(iXXX, COORDS)", "imageLoad(iXXX, COORDS)",	"imageLoad(iXXX, COORDS)",   "imageLoad(iXXX, COORDS)",
3943 		"imageLoad(iXXX, COORDS)", "imageLoad(iXXX, COORDS, 0)", "imageLoad(iXXX, COORDS, 0)"
3944 	};
3945 
3946 	static const GLchar* images[] = { "uimage1D",	 "uimage1DArray", "uimage2D",		 "uimage2DArray",
3947 									  "uimage3D",	 "uimageBuffer",  "uimageCube",	 "uimageCubeArray",
3948 									  "uimage2DRect", "uimage2DMS",	"uimage2DMSArray" };
3949 
3950 	static const GLchar* coordinates[] = {
3951 		"0",
3952 		"ivec2(0, 0)",
3953 		"ivec2(0, 0)",
3954 		"ivec3(0, 0, 0)",
3955 		"ivec3(0, 0, 0)",
3956 		"0",
3957 		"ivec3(0, 0, 0)",
3958 		"ivec3(0, 0, 0)",
3959 		"ivec2(0, 0)",
3960 		"ivec2(0, 0)",
3961 		"ivec3(0, 0, 0)",
3962 	};
3963 
3964 	static const GLuint depth  = 6;
3965 	static const GLuint height = 6;
3966 	static const GLuint width  = 6;
3967 
3968 	const Functions& gl = m_context.getRenderContext().getFunctions();
3969 
3970 	bool test_result = true;
3971 
3972 #if DEBUG_ENBALE_MESSAGE_CALLBACK
3973 	gl.debugMessageCallback(debug_proc, &m_context);
3974 	GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
3975 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
3976 
3977 	GLint  max_textures		 = 0;
3978 	GLint  max_image_samples = 0;
3979 	GLuint sum				 = 0;
3980 
3981 	/* Get max */
3982 	gl.getIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &max_textures);
3983 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3984 
3985 	/* Check if load/store from multisampled images is supported */
3986 	gl.getIntegerv(GL_MAX_IMAGE_SAMPLES, &max_image_samples);
3987 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3988 
3989 	/* Textures */
3990 	/* Storage */
3991 	std::vector<Texture> texture;
3992 	std::vector<GLuint>  texture_ids;
3993 	Buffer				 texture_buffer;
3994 
3995 	texture.resize(max_textures);
3996 	texture_ids.resize(max_textures);
3997 
3998 	/* Prepare */
3999 	for (GLint i = 0; i < max_textures; ++i)
4000 	{
4001 		GLenum target = getTarget(i);
4002 		if (target >= GL_TEXTURE_2D_MULTISAMPLE && max_image_samples == 0)
4003 			target = GL_TEXTURE_2D;
4004 
4005 		GLuint data[width * height * depth];
4006 
4007 		for (GLuint j = 0; j < width * height * depth; ++j)
4008 		{
4009 			data[j] = i;
4010 		}
4011 
4012 		sum += i;
4013 
4014 		bool is_array = false;
4015 
4016 		switch (target)
4017 		{
4018 		case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
4019 			is_array = true;
4020 		/* Intentional fallthrough */
4021 
4022 		case GL_TEXTURE_2D_MULTISAMPLE:
4023 			texture[i].InitStorage(m_context, target, 1, GL_R32UI, width, height, depth);
4024 			fillMSTexture(m_context, texture[i].m_id, i, is_array);
4025 			break;
4026 
4027 		case GL_TEXTURE_BUFFER:
4028 			texture_buffer.InitData(m_context, GL_TEXTURE_BUFFER, GL_DYNAMIC_COPY, sizeof(data), data);
4029 			texture[i].InitBuffer(m_context, GL_R32UI, texture_buffer.m_id);
4030 			break;
4031 
4032 		default:
4033 			texture[i].InitStorage(m_context, target, 1, GL_R32UI, width, height, depth);
4034 			Texture::Bind(gl, texture[i].m_id, target);
4035 			Texture::SubImage(gl, target, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height, depth,
4036 							  GL_RED_INTEGER, GL_UNSIGNED_INT, &data);
4037 			break;
4038 		}
4039 
4040 		/* Clean */
4041 		Texture::Bind(gl, 0, target);
4042 
4043 		texture_ids[i] = texture[i].m_id;
4044 	}
4045 
4046 	gl.bindImageTextures(0 /* first */, max_textures /* count */, &texture_ids[0]);
4047 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTextures");
4048 
4049 	/* SSBO */
4050 	Buffer ssb_buffer;
4051 	ssb_buffer.InitData(m_context, GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, sizeof(GLuint), 0 /* data */);
4052 
4053 	ssb_buffer.BindBase(0);
4054 
4055 	/* Prepare program */
4056 	size_t		load_position	= 0;
4057 	size_t		sum_position	 = 0;
4058 	std::string cs_source		 = cs;
4059 	GLint		max_target_index = (GLint)(max_image_samples > 0 ? s_n_texture_tragets : s_n_texture_tragets - 2);
4060 	for (GLint i = 0; i < max_textures; ++i)
4061 	{
4062 		size_t load_start_position = load_position;
4063 		size_t sum_start_position  = sum_position;
4064 
4065 		GLchar index[16];
4066 
4067 		sprintf(index, "%d", i);
4068 
4069 		const GLchar* coords	   = 0;
4070 		const GLchar* image_type   = 0;
4071 		const GLchar* loading_code = 0;
4072 
4073 		if (i < max_target_index)
4074 		{
4075 			coords		 = coordinates[i];
4076 			image_type   = images[i];
4077 			loading_code = loading[i];
4078 		}
4079 		else
4080 		{
4081 			coords		 = coordinates[2]; /* vec2(0.5f, 0.5f) */
4082 			image_type   = images[2];	  /* usampler2D */
4083 			loading_code = loading[2];	 /* texture(sXXX, COORDS) */
4084 		}
4085 
4086 		/* Add entry to ubo list */
4087 		replaceToken("IMAGE_LIST", load_position, "IMAGE\nIMAGE_LIST", cs_source);
4088 		load_position = load_start_position;
4089 
4090 		replaceToken("IMAGE", load_position, image, cs_source);
4091 		load_position = load_start_position;
4092 
4093 		replaceToken("XXX", load_position, index, cs_source);
4094 		replaceToken("IMAGE", load_position, image_type, cs_source);
4095 		replaceToken("XXX", load_position, index, cs_source);
4096 
4097 		/* Add entry to sum list */
4098 		replaceToken("SUM_LIST", sum_position, "LOADING + SUM_LIST", cs_source);
4099 		sum_position = sum_start_position;
4100 
4101 		replaceToken("LOADING", sum_position, loading_code, cs_source);
4102 		sum_position = sum_start_position;
4103 
4104 		replaceToken("XXX", sum_position, index, cs_source);
4105 		replaceToken("COORDS", sum_position, coords, cs_source);
4106 	}
4107 
4108 	/* Remove token for lists */
4109 	replaceToken(" + SUM_LIST", sum_position, "", cs_source);
4110 	replaceToken("IMAGE_LIST", load_position, "", cs_source);
4111 
4112 	Program program(m_context);
4113 	program.Init(cs_source.c_str(), "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
4114 
4115 	program.Use();
4116 
4117 	/* Set images */
4118 	for (GLint i = 0; i < max_textures; ++i)
4119 	{
4120 		gl.uniform1i(i, i);
4121 		GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
4122 	}
4123 
4124 	gl.dispatchCompute(1, 1, 1);
4125 	GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
4126 
4127 	gl.memoryBarrier(GL_ALL_BARRIER_BITS);
4128 	GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
4129 
4130 	GLuint* result = (GLuint*)gl.mapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY);
4131 	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
4132 
4133 	if (0 != memcmp(result, &sum, sizeof(sum)))
4134 	{
4135 		test_result = false;
4136 	}
4137 
4138 	gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
4139 	gl.getError(); /* Ignore error */
4140 
4141 	/* Set result */
4142 	if (true == test_result)
4143 	{
4144 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
4145 	}
4146 	else
4147 	{
4148 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4149 	}
4150 
4151 	/* Done */
4152 	return tcu::TestNode::STOP;
4153 }
4154 
4155 /** Constructor
4156  *
4157  * @param context Test context
4158  **/
DispatchBindSamplersTest(deqp::Context & context)4159 DispatchBindSamplersTest::DispatchBindSamplersTest(deqp::Context& context)
4160 	: TestCase(context, "dispatch_bind_samplers", "Tests BindSamplers with dispatch command")
4161 {
4162 	/* Nothing to be done */
4163 }
4164 
4165 /** Execute test
4166  *
4167  * @return tcu::TestNode::STOP
4168  **/
iterate()4169 tcu::TestNode::IterateResult DispatchBindSamplersTest::iterate()
4170 {
4171 	static const GLchar* cs = "#version 440 core\n"
4172 							  "\n"
4173 							  "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
4174 							  "\n"
4175 							  "SAMPLER_LIST\n"
4176 							  "layout (std140, binding = 0) buffer SSB {\n"
4177 							  "    uint sum;\n"
4178 							  "} ssb;\n"
4179 							  "\n"
4180 							  "void main()\n"
4181 							  "{\n"
4182 							  "    uvec4 sum = SUM_LIST;\n"
4183 							  "    ssb.sum = sum.r\n;"
4184 							  "}\n"
4185 							  "\n";
4186 
4187 	static const GLchar* sampler = "layout (location = XXX) uniform usampler2D sXXX;";
4188 
4189 	static const GLchar* sampling = "texture(sXXX, vec2(1.5f, 0.5f))";
4190 
4191 	static const GLuint depth  = 1;
4192 	static const GLuint height = 8;
4193 	static const GLuint width  = 8;
4194 
4195 	const Functions& gl = m_context.getRenderContext().getFunctions();
4196 
4197 	bool test_result = true;
4198 
4199 #if DEBUG_ENBALE_MESSAGE_CALLBACK
4200 	gl.debugMessageCallback(debug_proc, &m_context);
4201 	GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
4202 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
4203 
4204 	GLint max_textures = 0;
4205 
4206 	/* Get max */
4207 	gl.getIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &max_textures);
4208 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
4209 
4210 	/* Textures */
4211 	/* Storage */
4212 	std::vector<GLuint>  sampler_ids;
4213 	std::vector<Texture> texture;
4214 	std::vector<GLuint>  texture_ids;
4215 
4216 	sampler_ids.resize(max_textures);
4217 	texture.resize(max_textures);
4218 	texture_ids.resize(max_textures);
4219 
4220 	GLuint data[width * height * depth];
4221 
4222 	for (GLuint j = 0; j < width * height; ++j)
4223 	{
4224 		data[j] = 0;
4225 	}
4226 
4227 	{
4228 		const size_t last_line_offset		   = (height - 1) * width;
4229 		const size_t last_pixel_in_line_offset = width - 1;
4230 
4231 		for (GLuint j = 0; j < width; ++j)
4232 		{
4233 			data[j]					   = 1;
4234 			data[j + last_line_offset] = 1;
4235 		}
4236 
4237 		for (GLuint j = 0; j < height; ++j)
4238 		{
4239 			const size_t line_offset = j * width;
4240 
4241 			data[line_offset]							  = 1;
4242 			data[line_offset + last_pixel_in_line_offset] = 1;
4243 		}
4244 	}
4245 
4246 	/* Prepare */
4247 	for (GLint i = 0; i < max_textures; ++i)
4248 	{
4249 		texture[i].InitStorage(m_context, GL_TEXTURE_2D, 1, GL_R32UI, width, height, depth);
4250 		Texture::Bind(gl, texture[i].m_id, GL_TEXTURE_2D);
4251 		Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height, depth,
4252 						  GL_RED_INTEGER, GL_UNSIGNED_INT, &data);
4253 
4254 		texture_ids[i] = texture[i].m_id;
4255 	}
4256 
4257 	/* Clean */
4258 	Texture::Bind(gl, 0, GL_TEXTURE_2D);
4259 
4260 	/* Execute the test */
4261 	gl.bindTextures(0 /* first */, max_textures /* count */, &texture_ids[0]);
4262 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindTextures");
4263 
4264 	/* SSBO */
4265 	Buffer ssb_buffer;
4266 	ssb_buffer.InitData(m_context, GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, sizeof(GLuint), 0 /* data */);
4267 
4268 	ssb_buffer.BindBase(0);
4269 
4270 	/* Prepare program */
4271 	size_t		sam_position = 0;
4272 	size_t		sum_position = 0;
4273 	std::string cs_source	= cs;
4274 
4275 	for (GLint i = 0; i < max_textures; ++i)
4276 	{
4277 		size_t sam_start_position = sam_position;
4278 		size_t sum_start_position = sum_position;
4279 
4280 		GLchar index[16];
4281 
4282 		sprintf(index, "%d", i);
4283 
4284 		/* Add entry to ubo list */
4285 		replaceToken("SAMPLER_LIST", sam_position, "SAMPLER\nSAMPLER_LIST", cs_source);
4286 		sam_position = sam_start_position;
4287 
4288 		replaceToken("SAMPLER", sam_position, sampler, cs_source);
4289 		sam_position = sam_start_position;
4290 
4291 		replaceToken("XXX", sam_position, index, cs_source);
4292 		replaceToken("XXX", sam_position, index, cs_source);
4293 
4294 		/* Add entry to sum list */
4295 		replaceToken("SUM_LIST", sum_position, "SAMPLING + SUM_LIST", cs_source);
4296 		sum_position = sum_start_position;
4297 
4298 		replaceToken("SAMPLING", sum_position, sampling, cs_source);
4299 		sum_position = sum_start_position;
4300 
4301 		replaceToken("XXX", sum_position, index, cs_source);
4302 	}
4303 
4304 	/* Remove token for lists */
4305 	replaceToken(" + SUM_LIST", sum_position, "", cs_source);
4306 	replaceToken("SAMPLER_LIST", sam_position, "", cs_source);
4307 
4308 	Program program(m_context);
4309 	program.Init(cs_source.c_str(), "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
4310 
4311 	program.Use();
4312 
4313 	/* Set texture units */
4314 	for (GLint i = 0; i < max_textures; ++i)
4315 	{
4316 		gl.uniform1i(i, i);
4317 		GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
4318 	}
4319 
4320 	/* Prepare samplers */
4321 	gl.genSamplers(max_textures, &sampler_ids[0]);
4322 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenSamplers");
4323 
4324 	try
4325 	{
4326 		gl.bindSamplers(0 /* first */, max_textures /* count */, &sampler_ids[0]);
4327 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindSamplers");
4328 
4329 		for (GLint i = 0; i < max_textures; ++i)
4330 		{
4331 			gl.samplerParameteri(sampler_ids[i], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
4332 			gl.samplerParameteri(sampler_ids[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4333 			gl.samplerParameteri(sampler_ids[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4334 			GLU_EXPECT_NO_ERROR(gl.getError(), "SamplerParameteri");
4335 		}
4336 
4337 		gl.dispatchCompute(1, 1, 1);
4338 		GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
4339 
4340 		gl.memoryBarrier(GL_ALL_BARRIER_BITS);
4341 		GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
4342 	}
4343 	catch (const std::exception&)
4344 	{
4345 		gl.deleteSamplers(max_textures, &sampler_ids[0]);
4346 
4347 		TCU_FAIL("Unexpected error generated");
4348 	}
4349 
4350 	/* Remove samplers */
4351 	gl.deleteSamplers(max_textures, &sampler_ids[0]);
4352 
4353 	/* Verify results */
4354 	GLuint* result = (GLuint*)gl.mapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY);
4355 	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
4356 
4357 	if (0 != memcmp(result, &max_textures, sizeof(max_textures)))
4358 	{
4359 		test_result = false;
4360 	}
4361 
4362 	gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
4363 	gl.getError(); /* Ignore error */
4364 
4365 	/* Set result */
4366 	if (true == test_result)
4367 	{
4368 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
4369 	}
4370 	else
4371 	{
4372 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4373 	}
4374 
4375 	/* Done */
4376 	return tcu::TestNode::STOP;
4377 }
4378 
4379 /** Constructor
4380  *
4381  * @param context Test context
4382  **/
DrawBindVertexBuffersTest(deqp::Context & context)4383 DrawBindVertexBuffersTest::DrawBindVertexBuffersTest(deqp::Context& context)
4384 	: TestCase(context, "draw_bind_vertex_buffers", "Tests BindVertexBuffers command with drawArrays")
4385 {
4386 	/* Nothing to be done */
4387 }
4388 
4389 /** Execute test
4390  *
4391  * @return tcu::TestNode::STOP
4392  **/
iterate()4393 tcu::TestNode::IterateResult DrawBindVertexBuffersTest::iterate()
4394 {
4395 	static const GLchar* vs = "#version 440 core\n"
4396 							  "\n"
4397 							  "ATTRIBUTE_LIST\n"
4398 							  "\n"
4399 							  "out vec4 vs_gs_sum;\n"
4400 							  "\n"
4401 							  "void main()\n"
4402 							  "{\n"
4403 							  "    vs_gs_sum = SUM_LIST;\n"
4404 							  "}\n"
4405 							  "\n";
4406 
4407 	static const GLchar* gs = "#version 440 core\n"
4408 							  "\n"
4409 							  "layout(points)                           in;\n"
4410 							  "layout(triangle_strip, max_vertices = 4) out;\n"
4411 							  "\n"
4412 							  "in  vec4 vs_gs_sum[];\n"
4413 							  "out vec4 gs_fs_sum;\n"
4414 							  "\n"
4415 							  "void main()\n"
4416 							  "{\n"
4417 							  "    gs_fs_sum   = vs_gs_sum[0];\n"
4418 							  "    gl_Position = vec4(-1, -1, 0, 1);\n"
4419 							  "    EmitVertex();\n"
4420 							  "    gs_fs_sum   = vs_gs_sum[0];\n"
4421 							  "    gl_Position = vec4(-1, 1, 0, 1);\n"
4422 							  "    EmitVertex();\n"
4423 							  "    gs_fs_sum   = vs_gs_sum[0];\n"
4424 							  "    gl_Position = vec4(1, -1, 0, 1);\n"
4425 							  "    EmitVertex();\n"
4426 							  "    gs_fs_sum   = vs_gs_sum[0];\n"
4427 							  "    gl_Position = vec4(1, 1, 0, 1);\n"
4428 							  "    EmitVertex();\n"
4429 							  "}\n"
4430 							  "\n";
4431 
4432 	static const GLchar* fs = "#version 440 core\n"
4433 							  "\n"
4434 							  "in  vec4 gs_fs_sum;\n"
4435 							  "out vec4 fs_out;\n"
4436 							  "\n"
4437 							  "void main()\n"
4438 							  "{\n"
4439 							  "    fs_out = gs_fs_sum;\n"
4440 							  "}\n"
4441 							  "\n";
4442 
4443 	static const GLchar* attribute = "layout (location = XXX) in vec4 aXXX;";
4444 
4445 	static const GLuint height = 8;
4446 	static const GLuint width  = 8;
4447 
4448 	const Functions& gl = m_context.getRenderContext().getFunctions();
4449 
4450 	bool test_result = true;
4451 
4452 #if DEBUG_ENBALE_MESSAGE_CALLBACK
4453 	gl.debugMessageCallback(debug_proc, &m_context);
4454 	GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
4455 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
4456 
4457 	static const GLintptr attribute_size = 4 * sizeof(GLfloat);
4458 
4459 	GLint  max_buffers = 0;
4460 	GLuint vao		   = 0;
4461 
4462 	/* Get max */
4463 	gl.getIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &max_buffers);
4464 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
4465 
4466 	/* Storage */
4467 	Buffer				  buffer;
4468 	std::vector<GLuint>   buffer_ids;
4469 	std::vector<GLfloat>  data;
4470 	std::vector<GLintptr> offsets;
4471 	std::vector<GLsizei>  strides;
4472 
4473 	buffer_ids.resize(max_buffers);
4474 	data.resize(max_buffers * 4);
4475 	offsets.resize(max_buffers);
4476 	strides.resize(max_buffers);
4477 
4478 	/* Prepare data */
4479 	const GLfloat value = 1.0f / (GLfloat)max_buffers;
4480 
4481 	for (GLint i = 0; i < max_buffers; ++i)
4482 	{
4483 		data[i * 4 + 0] = value;
4484 		data[i * 4 + 1] = value;
4485 		data[i * 4 + 2] = value;
4486 		data[i * 4 + 3] = value;
4487 	}
4488 
4489 	/* Prepare buffer */
4490 	buffer.InitData(m_context, GL_ARRAY_BUFFER, GL_DYNAMIC_COPY, data.size() * sizeof(GLfloat), &data[0]);
4491 
4492 	for (GLint i = 0; i < max_buffers; ++i)
4493 	{
4494 		buffer_ids[i] = buffer.m_id;
4495 		offsets[i]	= i * attribute_size;
4496 		strides[i]	= attribute_size;
4497 	}
4498 
4499 	/* Prepare FBO */
4500 	Framebuffer framebuffer(m_context);
4501 	Texture		texture;
4502 
4503 	texture.InitStorage(m_context, GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, width, height, 1 /* depth */);
4504 
4505 	/* */
4506 	Framebuffer::Generate(gl, framebuffer.m_id);
4507 	Framebuffer::Bind(gl, GL_DRAW_FRAMEBUFFER, framebuffer.m_id);
4508 	Framebuffer::AttachTexture(gl, GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.m_id, 0 /* level */, width,
4509 							   height);
4510 
4511 	/* Prepare program */
4512 	size_t		attr_position = 0;
4513 	size_t		sum_position  = 0;
4514 	std::string vs_source	 = vs;
4515 	for (GLint i = 0; i < max_buffers; ++i)
4516 	{
4517 		size_t attr_start_position = attr_position;
4518 		size_t sum_start_position  = sum_position;
4519 
4520 		GLchar index[16];
4521 
4522 		sprintf(index, "%d", i);
4523 
4524 		/* Add entry to ubo list */
4525 		replaceToken("ATTRIBUTE_LIST", attr_position, "ATTRIBUTE\nATTRIBUTE_LIST", vs_source);
4526 		attr_position = attr_start_position;
4527 
4528 		replaceToken("ATTRIBUTE", attr_position, attribute, vs_source);
4529 		attr_position = attr_start_position;
4530 
4531 		replaceToken("XXX", attr_position, index, vs_source);
4532 		replaceToken("XXX", attr_position, index, vs_source);
4533 
4534 		/* Add entry to sum list */
4535 		replaceToken("SUM_LIST", sum_position, "aXXX + SUM_LIST", vs_source);
4536 		sum_position = sum_start_position;
4537 
4538 		replaceToken("XXX", sum_position, index, vs_source);
4539 	}
4540 
4541 	/* Remove token for lists */
4542 	replaceToken(" + SUM_LIST", sum_position, "", vs_source);
4543 	replaceToken("ATTRIBUTE_LIST", attr_position, "", vs_source);
4544 
4545 	Program program(m_context);
4546 	program.Init("" /* cs */, fs, gs, "" /* tcs */, "" /* tes */, vs_source.c_str());
4547 
4548 	program.Use();
4549 
4550 	gl.genVertexArrays(1, &vao);
4551 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
4552 
4553 	try
4554 	{
4555 		gl.bindVertexArray(vao);
4556 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArrays");
4557 
4558 		for (GLint i = 0; i < max_buffers; ++i)
4559 		{
4560 			gl.enableVertexAttribArray(i);
4561 			GLU_EXPECT_NO_ERROR(gl.getError(), "EnableVertexAttribArray");
4562 		}
4563 
4564 		/* */
4565 		gl.bindVertexBuffers(0, max_buffers, &buffer_ids[0], &offsets[0], &strides[0]);
4566 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexBuffers");
4567 
4568 		/* */
4569 		gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
4570 		GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
4571 
4572 		for (GLint i = 0; i < max_buffers; ++i)
4573 		{
4574 			gl.disableVertexAttribArray(i);
4575 			GLU_EXPECT_NO_ERROR(gl.getError(), "DisableVertexAttribArray");
4576 		}
4577 	}
4578 	catch (const std::exception&)
4579 	{
4580 		gl.deleteVertexArrays(1, &vao);
4581 
4582 		TCU_FAIL("Unexpected error generated");
4583 	}
4584 
4585 	gl.deleteVertexArrays(1, &vao);
4586 	GLU_EXPECT_NO_ERROR(gl.getError(), "DeleteVertexArrays");
4587 
4588 	/* Verify results */
4589 	GLuint pixels[width * height];
4590 	for (GLuint i = 0; i < width * height; ++i)
4591 	{
4592 		pixels[i] = 0;
4593 	}
4594 
4595 	Texture::Bind(gl, texture.m_id, GL_TEXTURE_2D);
4596 
4597 	Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
4598 
4599 	/* Unbind */
4600 	Texture::Bind(gl, 0, GL_TEXTURE_2D);
4601 
4602 	/* Verify */
4603 	for (GLuint i = 0; i < width * height; ++i)
4604 	{
4605 		if (0xffffffff != pixels[i])
4606 		{
4607 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << (GLuint)pixels[i]
4608 												<< " at offset: " << i << tcu::TestLog::EndMessage;
4609 
4610 			test_result = false;
4611 
4612 			break;
4613 		}
4614 	}
4615 
4616 	/* Set result */
4617 	if (true == test_result)
4618 	{
4619 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
4620 	}
4621 	else
4622 	{
4623 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4624 	}
4625 
4626 	/* Done */
4627 	return tcu::TestNode::STOP;
4628 }
4629 } /* MultiBind */
4630 
4631 /** Constructor.
4632  *
4633  *  @param context Rendering context.
4634  **/
MultiBindTests(deqp::Context & context)4635 MultiBindTests::MultiBindTests(deqp::Context& context)
4636 	: TestCaseGroup(context, "multi_bind", "Verifies \"multi bind\" functionality")
4637 {
4638 	/* Left blank on purpose */
4639 }
4640 
4641 /** Initializes a multi_bind test group.
4642  *
4643  **/
init(void)4644 void MultiBindTests::init(void)
4645 {
4646 	addChild(new MultiBind::DispatchBindTexturesTest(m_context));
4647 
4648 	addChild(new MultiBind::ErrorsBindBuffersTest(m_context));
4649 	addChild(new MultiBind::ErrorsBindTexturesTest(m_context));
4650 	addChild(new MultiBind::ErrorsBindSamplersTest(m_context));
4651 	addChild(new MultiBind::ErrorsBindImageTexturesTest(m_context));
4652 	addChild(new MultiBind::ErrorsBindVertexBuffersTest(m_context));
4653 	addChild(new MultiBind::FunctionalBindBuffersBaseTest(m_context));
4654 	addChild(new MultiBind::FunctionalBindBuffersRangeTest(m_context));
4655 	addChild(new MultiBind::FunctionalBindTexturesTest(m_context));
4656 	addChild(new MultiBind::FunctionalBindSamplersTest(m_context));
4657 	addChild(new MultiBind::FunctionalBindImageTexturesTest(m_context));
4658 	addChild(new MultiBind::FunctionalBindVertexBuffersTest(m_context));
4659 	addChild(new MultiBind::DispatchBindBuffersBaseTest(m_context));
4660 	addChild(new MultiBind::DispatchBindBuffersRangeTest(m_context));
4661 
4662 	addChild(new MultiBind::DispatchBindImageTexturesTest(m_context));
4663 	addChild(new MultiBind::DispatchBindSamplersTest(m_context));
4664 	addChild(new MultiBind::DrawBindVertexBuffersTest(m_context));
4665 }
4666 
4667 } /* gl4cts namespace */
4668