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