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