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