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
45using namespace glw;
46
47namespace gl4cts
48{
49namespace 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 */
63void 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 **/
157class Buffer
158{
159public:
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
197private:
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 **/
208class Framebuffer
209{
210public:
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
233private:
234	/* Private fields */
235	deqp::Context& m_context;
236};
237
238/** Represents shader instance.
239 * Provides basic functionality for shaders.
240 **/
241class Shader
242{
243public:
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
267private:
268	/* Private fields */
269	deqp::Context& m_context;
270};
271
272/** Represents program instance.
273 * Provides basic functionality
274 **/
275class Program
276{
277public:
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
315private:
316	/* Private fields */
317	deqp::Context& m_context;
318};
319
320/** Represents texture instance
321 **/
322class Texture
323{
324public:
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
373private:
374	/* Private fields */
375	deqp::Context* m_context;
376};
377
378/* Buffer constants */
379const GLuint Buffer::m_invalid_id = -1;
380
381/** Constructor.
382 *
383 **/
384Buffer::Buffer() : m_id(m_invalid_id), m_context(0), m_target(GL_ARRAY_BUFFER)
385{
386}
387
388/** Destructor
389 *
390 **/
391Buffer::~Buffer()
392{
393	Release();
394
395	m_context = 0;
396}
397
398/** Initialize buffer instance
399 *
400 * @param context CTS context.
401 **/
402void 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 **/
417void 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 **/
434void 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 **/
448void 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 **/
464void 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 **/
482void 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 **/
495void 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 **/
509void 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 **/
521void 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 **/
544void 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 */
552const GLuint Framebuffer::m_invalid_id = -1;
553
554/** Constructor.
555 *
556 * @param context CTS context.
557 **/
558Framebuffer::Framebuffer(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
559{
560	/* Nothing to done here */
561}
562
563/** Destructor
564 *
565 **/
566Framebuffer::~Framebuffer()
567{
568	Release();
569}
570
571/** Release texture instance
572 *
573 **/
574void 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 **/
595void 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 **/
611void 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 **/
620void 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 */
636const GLuint Program::m_invalid_id = 0;
637
638/** Constructor.
639 *
640 * @param context CTS context.
641 **/
642Program::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 **/
658Program::~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 **/
672void 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 **/
706void 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 **/
729void 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 **/
742void 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 **/
759void 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 **/
777void 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 **/
813void 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 */
820const GLuint Shader::m_invalid_id = 0;
821
822/** Constructor.
823 *
824 * @param context CTS context.
825 **/
826Shader::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 **/
834Shader::~Shader()
835{
836	Release();
837}
838
839/** Initialize shader instance
840 *
841 * @param stage  Shader stage
842 * @param source Source code
843 **/
844void 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 **/
867void 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 **/
883void 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 **/
922void 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 **/
941void 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 */
950const GLuint Texture::m_invalid_id = -1;
951
952/** Constructor.
953 *
954 **/
955Texture::Texture() : m_id(m_invalid_id), m_context(0)
956{
957	/* Nothing to done here */
958}
959
960/** Destructor
961 *
962 **/
963Texture::~Texture()
964{
965	Release();
966}
967
968/** Initialize texture instance
969 *
970 * @param context Test context
971 **/
972void 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 **/
985void 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 **/
1009void 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 **/
1025void 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 **/
1042void 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 **/
1060void 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 **/
1107void 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 **/
1130void 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 **/
1145void 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 **/
1165void 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 **/
1217void 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 **/
1283void 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 */
1321struct 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 */
1331struct textureTargetInfo
1332{
1333	GLenum		  m_target;
1334	GLenum		  m_pname_binding;
1335	const GLchar* m_name;
1336};
1337
1338/* Collects information about buffers */
1339static 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
1352static const size_t s_n_buffer_tragets = sizeof(s_buffer_infos) / sizeof(s_buffer_infos[0]);
1353
1354/* Collects information about textures */
1355static 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
1369static 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 */
1392void 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 **/
1402void 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 **/
1428void 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 **/
1464void 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 **/
1489void 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 **/
1560GLenum 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 **/
1578GLenum 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 **/
1597void 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 **/
1612ErrorsBindBuffersTest::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 **/
1622tcu::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 **/
1822ErrorsBindTexturesTest::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 **/
1832tcu::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 **/
1939ErrorsBindSamplersTest::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 **/
1949tcu::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 **/
2057ErrorsBindImageTexturesTest::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 **/
2068tcu::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 **/
2219ErrorsBindVertexBuffersTest::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 **/
2230tcu::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 **/
2376FunctionalBindBuffersBaseTest::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 **/
2386tcu::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 **/
2542FunctionalBindBuffersRangeTest::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 **/
2552tcu::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 **/
2715FunctionalBindTexturesTest::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 **/
2725tcu::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 **/
2888FunctionalBindSamplersTest::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 **/
2898tcu::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 **/
3036FunctionalBindImageTexturesTest::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 **/
3046tcu::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 **/
3213FunctionalBindVertexBuffersTest::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 **/
3223tcu::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 **/
3369DispatchBindBuffersBaseTest::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 **/
3379tcu::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 **/
3525DispatchBindBuffersRangeTest::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 **/
3535tcu::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 **/
3659DispatchBindTexturesTest::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 **/
3669tcu::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		/* Intended pass-through */
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 **/
3910DispatchBindImageTexturesTest::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 **/
3920tcu::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		/* Intended pass-through */
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 **/
4159DispatchBindSamplersTest::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 **/
4169tcu::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 **/
4383DrawBindVertexBuffersTest::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 **/
4393tcu::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 **/
4635MultiBindTests::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 **/
4644void 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