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