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 /* Sanity checks */
745 if ((m_invalid_id == program_id) || (Shader::m_invalid_id == shader_id))
746 {
747 return;
748 }
749
750 gl.attachShader(program_id, shader_id);
751 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
752 }
753
754 /** Create program instance
755 *
756 * @param gl GL functions
757 * @param out_id Id of program
758 **/
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 break;
1099 }
1100 }
1101
1102 /** Generate texture instance
1103 *
1104 * @param gl GL functions
1105 * @param out_id Id of texture
1106 **/
Generate(const glw::Functions & gl,glw::GLuint & out_id)1107 void Texture::Generate(const glw::Functions& gl, glw::GLuint& out_id)
1108 {
1109 GLuint id = m_invalid_id;
1110
1111 gl.genTextures(1, &id);
1112 GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
1113
1114 if (m_invalid_id == id)
1115 {
1116 TCU_FAIL("Invalid id");
1117 }
1118
1119 out_id = id;
1120 }
1121
1122 /** Get texture data
1123 *
1124 * @param gl GL functions
1125 * @param target Texture target
1126 * @param format Format of data
1127 * @param type Type of data
1128 * @param out_data Buffer for data
1129 **/
GetData(const glw::Functions & gl,glw::GLint level,glw::GLenum target,glw::GLenum format,glw::GLenum type,glw::GLvoid * out_data)1130 void Texture::GetData(const glw::Functions& gl, glw::GLint level, glw::GLenum target, glw::GLenum format,
1131 glw::GLenum type, glw::GLvoid* out_data)
1132 {
1133 gl.getTexImage(target, level, format, type, out_data);
1134 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
1135 }
1136
1137 /** Generate texture instance
1138 *
1139 * @param gl GL functions
1140 * @param target Texture target
1141 * @param level Mipmap level
1142 * @param pname Parameter to query
1143 * @param param Result of query
1144 **/
GetLevelParameter(const glw::Functions & gl,glw::GLenum target,glw::GLint level,glw::GLenum pname,glw::GLint * param)1145 void Texture::GetLevelParameter(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLenum pname,
1146 glw::GLint* param)
1147 {
1148 gl.getTexLevelParameteriv(target, level, pname, param);
1149 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexLevelParameteriv");
1150 }
1151
1152 /** Set contents of texture
1153 *
1154 * @param gl GL functions
1155 * @param target Texture target
1156 * @param level Mipmap level
1157 * @param internal_format Format of data
1158 * @param width Width of texture
1159 * @param height Height of texture
1160 * @param depth Depth of texture
1161 * @param format Format of data
1162 * @param type Type of data
1163 * @param data Buffer with image data
1164 **/
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)1165 void Texture::Image(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLenum internal_format,
1166 glw::GLuint width, glw::GLuint height, glw::GLuint depth, glw::GLenum format, glw::GLenum type,
1167 const glw::GLvoid* data)
1168 {
1169 switch (target)
1170 {
1171 case GL_TEXTURE_1D:
1172 gl.texImage1D(target, level, internal_format, width, 0 /* border */, format, type, data);
1173 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage1D");
1174 break;
1175 case GL_TEXTURE_1D_ARRAY:
1176 case GL_TEXTURE_2D:
1177 case GL_TEXTURE_RECTANGLE:
1178 gl.texImage2D(target, level, internal_format, width, height, 0 /* border */, format, type, data);
1179 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage2D");
1180 break;
1181 case GL_TEXTURE_CUBE_MAP:
1182 gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, internal_format, width, height, 0 /* border */, format,
1183 type, data);
1184 gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, internal_format, width, height, 0 /* border */, format,
1185 type, data);
1186 gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, internal_format, width, height, 0 /* border */, format,
1187 type, data);
1188 gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, internal_format, width, height, 0 /* border */, format,
1189 type, data);
1190 gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, internal_format, width, height, 0 /* border */, format,
1191 type, data);
1192 gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, internal_format, width, height, 0 /* border */, format,
1193 type, data);
1194 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage2D");
1195 break;
1196 case GL_TEXTURE_3D:
1197 case GL_TEXTURE_2D_ARRAY:
1198 gl.texImage3D(target, level, internal_format, width, height, depth, 0 /* border */, format, type, data);
1199 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage3D");
1200 break;
1201 default:
1202 TCU_FAIL("Invliad enum");
1203 break;
1204 }
1205 }
1206
1207 /** Allocate storage for texture
1208 *
1209 * @param gl GL functions
1210 * @param target Texture target
1211 * @param levels Number of levels
1212 * @param internal_format Internal format of texture
1213 * @param width Width of texture
1214 * @param height Height of texture
1215 * @param depth Depth of texture
1216 **/
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)1217 void Texture::Storage(const glw::Functions& gl, glw::GLenum target, glw::GLsizei levels, glw::GLenum internal_format,
1218 glw::GLuint width, glw::GLuint height, glw::GLuint depth, bool allow_error)
1219 {
1220 switch (target)
1221 {
1222 case GL_TEXTURE_1D:
1223 gl.texStorage1D(target, levels, internal_format, width);
1224 if (!allow_error)
1225 {
1226 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage1D");
1227 }
1228 break;
1229 case GL_TEXTURE_1D_ARRAY:
1230 case GL_TEXTURE_2D:
1231 case GL_TEXTURE_RECTANGLE:
1232 case GL_TEXTURE_CUBE_MAP:
1233 gl.texStorage2D(target, levels, internal_format, width, height);
1234 if (!allow_error)
1235 {
1236 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
1237 }
1238 break;
1239 case GL_TEXTURE_2D_MULTISAMPLE:
1240 gl.texStorage2DMultisample(target, levels, internal_format, width, height, GL_FALSE);
1241 if (!allow_error)
1242 {
1243 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2DMultisample");
1244 }
1245 break;
1246 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1247 gl.texStorage3DMultisample(target, levels, internal_format, width, height, depth, GL_FALSE);
1248 if (!allow_error)
1249 {
1250 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage3DMultisample");
1251 }
1252 break;
1253 case GL_TEXTURE_3D:
1254 case GL_TEXTURE_2D_ARRAY:
1255 case GL_TEXTURE_CUBE_MAP_ARRAY:
1256 gl.texStorage3D(target, levels, internal_format, width, height, depth);
1257 if (!allow_error)
1258 {
1259 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage3D");
1260 }
1261 break;
1262 default:
1263 TCU_FAIL("Invliad enum");
1264 break;
1265 }
1266 }
1267
1268 /** Set contents of texture
1269 *
1270 * @param gl GL functions
1271 * @param target Texture target
1272 * @param level Mipmap level
1273 * @param x X offset
1274 * @param y Y offset
1275 * @param z Z offset
1276 * @param width Width of texture
1277 * @param height Height of texture
1278 * @param depth Depth of texture
1279 * @param format Format of data
1280 * @param type Type of data
1281 * @param pixels Buffer with image data
1282 **/
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)1283 void Texture::SubImage(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLint x, glw::GLint y,
1284 glw::GLint z, glw::GLsizei width, glw::GLsizei height, glw::GLsizei depth, glw::GLenum format,
1285 glw::GLenum type, const glw::GLvoid* pixels)
1286 {
1287 switch (target)
1288 {
1289 case GL_TEXTURE_1D:
1290 gl.texSubImage1D(target, level, x, width, format, type, pixels);
1291 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage1D");
1292 break;
1293 case GL_TEXTURE_1D_ARRAY:
1294 case GL_TEXTURE_2D:
1295 case GL_TEXTURE_RECTANGLE:
1296 gl.texSubImage2D(target, level, x, y, width, height, format, type, pixels);
1297 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
1298 break;
1299 case GL_TEXTURE_CUBE_MAP:
1300 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, x, y, width, height, format, type, pixels);
1301 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, x, y, width, height, format, type, pixels);
1302 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, x, y, width, height, format, type, pixels);
1303 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, x, y, width, height, format, type, pixels);
1304 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, x, y, width, height, format, type, pixels);
1305 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, x, y, width, height, format, type, pixels);
1306 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
1307 break;
1308 case GL_TEXTURE_3D:
1309 case GL_TEXTURE_2D_ARRAY:
1310 case GL_TEXTURE_CUBE_MAP_ARRAY:
1311 gl.texSubImage3D(target, level, x, y, z, width, height, depth, format, type, pixels);
1312 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage3D");
1313 break;
1314 default:
1315 TCU_FAIL("Invliad enum");
1316 break;
1317 }
1318 }
1319
1320 /* Gather info about buffer target */
1321 struct bufferTargetInfo
1322 {
1323 GLenum m_target;
1324 GLenum m_pname_alignment;
1325 GLenum m_pname_binding;
1326 GLenum m_pname_max;
1327 GLenum m_pname_max_size;
1328 };
1329
1330 /* Gather info about texture target */
1331 struct textureTargetInfo
1332 {
1333 GLenum m_target;
1334 GLenum m_pname_binding;
1335 const GLchar* m_name;
1336 };
1337
1338 /* Collects information about buffers */
1339 static const bufferTargetInfo s_buffer_infos[] = {
1340 { GL_ATOMIC_COUNTER_BUFFER, 0, GL_ATOMIC_COUNTER_BUFFER_BINDING, GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS,
1341 GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE },
1342 {
1343 GL_TRANSFORM_FEEDBACK_BUFFER, 0, GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, GL_MAX_TRANSFORM_FEEDBACK_BUFFERS,
1344 GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,
1345 },
1346 { GL_UNIFORM_BUFFER, GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, GL_UNIFORM_BUFFER_BINDING, GL_MAX_UNIFORM_BUFFER_BINDINGS,
1347 GL_MAX_UNIFORM_BLOCK_SIZE },
1348 { GL_SHADER_STORAGE_BUFFER, GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, GL_SHADER_STORAGE_BUFFER_BINDING,
1349 GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, GL_MAX_SHADER_STORAGE_BLOCK_SIZE },
1350 };
1351
1352 static const size_t s_n_buffer_tragets = sizeof(s_buffer_infos) / sizeof(s_buffer_infos[0]);
1353
1354 /* Collects information about textures */
1355 static const textureTargetInfo s_texture_infos[] = {
1356 { GL_TEXTURE_1D, GL_TEXTURE_BINDING_1D, "1D" },
1357 { GL_TEXTURE_1D_ARRAY, GL_TEXTURE_BINDING_1D_ARRAY, "1D_ARRAY" },
1358 { GL_TEXTURE_2D, GL_TEXTURE_BINDING_2D, "2D" },
1359 { GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BINDING_2D_ARRAY, "2D_ARRAY" },
1360 { GL_TEXTURE_3D, GL_TEXTURE_BINDING_3D, "3D" },
1361 { GL_TEXTURE_BUFFER, GL_TEXTURE_BINDING_BUFFER, "BUFFER" },
1362 { GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BINDING_CUBE_MAP, "CUBE" },
1363 { GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_BINDING_CUBE_MAP_ARRAY, "CUBE_ARRAY" },
1364 { GL_TEXTURE_RECTANGLE, GL_TEXTURE_BINDING_RECTANGLE, "RECTANGLE" },
1365 { GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_BINDING_2D_MULTISAMPLE, "2D_MS" },
1366 { GL_TEXTURE_2D_MULTISAMPLE_ARRAY, GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY, "2D_MS_ARRAY" }
1367 };
1368
1369 static const size_t s_n_texture_tragets = sizeof(s_texture_infos) / sizeof(s_texture_infos[0]);
1370
1371 /** Macro, verifies generated error, logs error message and throws failure
1372 *
1373 * @param expected_error Expected error value
1374 * @param error_message Message logged if generated error is not the expected one
1375 **/
1376 #define CHECK_ERROR(expected_error, error_message) \
1377 { \
1378 GLenum generated_error = gl.getError(); \
1379 \
1380 if (expected_error != generated_error) \
1381 { \
1382 m_context.getTestContext().getLog() \
1383 << tcu::TestLog::Message << "File: " << __FILE__ << ", line: " << __LINE__ \
1384 << ". Got wrong error: " << glu::getErrorStr(generated_error) \
1385 << ", expected: " << glu::getErrorStr(expected_error) << ", message: " << error_message \
1386 << tcu::TestLog::EndMessage; \
1387 TCU_FAIL("Invalid error generated"); \
1388 } \
1389 }
1390
1391 /* Prototypes */
1392 void replaceToken(const GLchar* token, size_t& search_position, const GLchar* text, std::string& string);
1393
1394 /** Checks binding
1395 *
1396 * @param context Test contex
1397 * @param pname Pname of binding
1398 * @param index Index of binding
1399 * @param target_name Name of target
1400 * @param expected_value Expected value of binding
1401 **/
checkBinding(deqp::Context & context,GLenum pname,GLuint index,const std::string & target_name,GLint expected_value)1402 void checkBinding(deqp::Context& context, GLenum pname, GLuint index, const std::string& target_name,
1403 GLint expected_value)
1404 {
1405 const Functions& gl = context.getRenderContext().getFunctions();
1406
1407 GLint binding = -1;
1408
1409 gl.getIntegeri_v(pname, index, &binding);
1410 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegeri_v");
1411
1412 if (binding != expected_value)
1413 {
1414 context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid binding: " << binding
1415 << ", expected: " << expected_value << ". Target: " << target_name
1416 << " at index: " << index << tcu::TestLog::EndMessage;
1417 TCU_FAIL("Invalid binding");
1418 }
1419 }
1420
1421 /** Checks bindings for given texture unit
1422 *
1423 * @param context Test contex
1424 * @param pname Binding pname of <expected_value>
1425 * @param index Index of texture unit
1426 * @param expected_value Expected value of binding at <pname> target
1427 **/
checkTextureBinding(deqp::Context & context,GLenum pname,GLuint index,GLint expected_value)1428 void checkTextureBinding(deqp::Context& context, GLenum pname, GLuint index, GLint expected_value)
1429 {
1430 const Functions& gl = context.getRenderContext().getFunctions();
1431
1432 for (size_t i = 0; i < s_n_texture_tragets; ++i)
1433 {
1434 const GLenum pname_binding = s_texture_infos[i].m_pname_binding;
1435 const GLchar* target_name = s_texture_infos[i].m_name;
1436
1437 GLint binding = -1;
1438 GLint value = 0;
1439
1440 gl.getIntegeri_v(pname_binding, index, &binding);
1441 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegeri_v");
1442
1443 if (pname_binding == pname)
1444 {
1445 value = (GLint)expected_value;
1446 }
1447
1448 if (binding != value)
1449 {
1450 context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid binding: " << binding
1451 << ", expected: " << expected_value << ". Target: " << target_name
1452 << " at index: " << index << tcu::TestLog::EndMessage;
1453 TCU_FAIL("Invalid binding");
1454 }
1455 }
1456 }
1457
1458 /** Checks binding
1459 *
1460 * @param context Test context
1461 * @param index Index of binding
1462 * @param expected_value Expected value of binding
1463 **/
checkVertexAttribBinding(deqp::Context & context,GLuint index,GLint expected_value)1464 void checkVertexAttribBinding(deqp::Context& context, GLuint index, GLint expected_value)
1465 {
1466 const Functions& gl = context.getRenderContext().getFunctions();
1467
1468 GLint binding = -1;
1469
1470 gl.getVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &binding);
1471 GLU_EXPECT_NO_ERROR(gl.getError(), "GetVertexAttribiv");
1472
1473 if (binding != expected_value)
1474 {
1475 context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid binding: " << binding
1476 << ", expected: " << expected_value << ". Target: Vertex attribute"
1477 << " at index: " << index << tcu::TestLog::EndMessage;
1478 TCU_FAIL("Invalid binding");
1479 }
1480 }
1481
1482 /** Fills MS texture with specified value
1483 *
1484 * @param context Test context
1485 * @param texture_id Index of binding
1486 * @param value Value for texture
1487 * @param is_array Selects if array target should be used
1488 **/
fillMSTexture(deqp::Context & context,GLuint texture_id,GLuint value,bool is_array)1489 void fillMSTexture(deqp::Context& context, GLuint texture_id, GLuint value, bool is_array)
1490 {
1491 /* */
1492 static const GLchar* cs = "#version 430 core\n"
1493 "\n"
1494 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1495 "\n"
1496 "layout (location = 0) writeonly uniform IMAGE uni_image;\n"
1497 "\n"
1498 "layout (location = 1) uniform uint uni_value;\n"
1499 "\n"
1500 "void main()\n"
1501 "{\n"
1502 " const POINT;\n"
1503 "\n"
1504 " imageStore(uni_image, point, 0, uvec4(uni_value, 0, 0, 0));\n"
1505 "}\n"
1506 "\n";
1507
1508 static const GLchar* array_image = "uimage2DMSArray";
1509 static const GLchar* array_point = "ivec3 point = ivec3(gl_WorkGroupID.x, gl_WorkGroupID.y, 0)";
1510 static const GLchar* regular_image = "uimage2DMS";
1511 static const GLchar* regular_point = "ivec2 point = ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y)";
1512
1513 /* */
1514 const Functions& gl = context.getRenderContext().getFunctions();
1515 const GLchar* image = (true == is_array) ? array_image : regular_image;
1516 const GLchar* point = (true == is_array) ? array_point : regular_point;
1517 size_t position = 0;
1518 std::string source = cs;
1519
1520 /* */
1521 replaceToken("IMAGE", position, image, source);
1522 replaceToken("POINT", position, point, source);
1523
1524 /* */
1525 Program program(context);
1526 program.Init(source.c_str(), "", "", "", "", "");
1527 program.Use();
1528
1529 /* */
1530 if (true == is_array)
1531 {
1532 gl.bindImageTexture(0 /* unit */, texture_id, 0 /* level */, GL_TRUE /* layered */, 0 /* layer */,
1533 GL_WRITE_ONLY, GL_R32UI);
1534 }
1535 else
1536 {
1537 gl.bindImageTexture(0 /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
1538 GL_WRITE_ONLY, GL_R32UI);
1539 }
1540
1541 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
1542
1543 gl.uniform1i(0 /* location */, 0 /* image unit*/);
1544 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
1545
1546 gl.uniform1ui(1 /* location */, value /* uni_value */);
1547 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1ui");
1548
1549 /* */
1550 gl.dispatchCompute(6, 6, 1);
1551 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
1552 }
1553
1554 /** Get texture binding pname for given index
1555 *
1556 * @param index Index of texture target
1557 *
1558 * @return Pname
1559 **/
getBinding(GLuint index)1560 GLenum getBinding(GLuint index)
1561 {
1562 if (index < s_n_texture_tragets)
1563 {
1564 return s_texture_infos[index].m_pname_binding;
1565 }
1566 else
1567 {
1568 return GL_TEXTURE_BINDING_2D;
1569 }
1570 }
1571
1572 /** Get texture target for given index
1573 *
1574 * @param index Index of texture target
1575 *
1576 * @return Target
1577 **/
getTarget(GLuint index)1578 GLenum getTarget(GLuint index)
1579 {
1580 if (index < s_n_texture_tragets)
1581 {
1582 return s_texture_infos[index].m_target;
1583 }
1584 else
1585 {
1586 return GL_TEXTURE_2D;
1587 }
1588 }
1589
1590 /** Replace first occurance of <token> with <text> in <string> starting at <search_posistion>
1591 *
1592 * @param token Token string
1593 * @param search_position Position at which find will start, it is updated to position at which replaced text ends
1594 * @param text String that will be used as replacement for <token>
1595 * @param string String to work on
1596 **/
replaceToken(const GLchar * token,size_t & search_position,const GLchar * text,std::string & string)1597 void replaceToken(const GLchar* token, size_t& search_position, const GLchar* text, std::string& string)
1598 {
1599 const size_t text_length = strlen(text);
1600 const size_t token_length = strlen(token);
1601 const size_t token_position = string.find(token, search_position);
1602
1603 string.replace(token_position, token_length, text, text_length);
1604
1605 search_position = token_position + text_length;
1606 }
1607
1608 /** Constructor
1609 *
1610 * @param context Test context
1611 **/
ErrorsBindBuffersTest(deqp::Context & context)1612 ErrorsBindBuffersTest::ErrorsBindBuffersTest(deqp::Context& context)
1613 : TestCase(context, "errors_bind_buffers", "Verifies that proper errors are generated by buffer binding routines")
1614 {
1615 /* Nothing to be done */
1616 }
1617
1618 /** Execute test
1619 *
1620 * @return tcu::TestNode::STOP
1621 **/
iterate()1622 tcu::TestNode::IterateResult ErrorsBindBuffersTest::iterate()
1623 {
1624 const Functions& gl = m_context.getRenderContext().getFunctions();
1625
1626 #if DEBUG_ENBALE_MESSAGE_CALLBACK
1627 gl.debugMessageCallback(debug_proc, &m_context);
1628 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
1629 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
1630
1631 /* - INVALID_ENUM when <target> is not valid; */
1632 {
1633 static const GLintptr buffer_size = 16;
1634 static const GLsizei count = 1;
1635 static const GLuint first = 0;
1636 static const GLintptr offset = 4;
1637 static const GLintptr size = buffer_size - offset;
1638
1639 Buffer buffer;
1640
1641 buffer.InitData(m_context, GL_ARRAY_BUFFER, GL_DYNAMIC_COPY, buffer_size, 0 /* data */);
1642
1643 gl.bindBuffersBase(GL_ARRAY_BUFFER, first, count, &buffer.m_id);
1644 CHECK_ERROR(GL_INVALID_ENUM, "BindBuffersBase with invalid <target>");
1645
1646 gl.bindBuffersRange(GL_ARRAY_BUFFER, first, count, &buffer.m_id, &offset, &size);
1647 CHECK_ERROR(GL_INVALID_ENUM, "BindBuffersRange with invalid <target>");
1648 }
1649
1650 for (size_t i = 0; i < s_n_buffer_tragets; ++i)
1651 {
1652 static const GLsizei n_buffers = 4;
1653
1654 const GLenum pname_alignment = s_buffer_infos[i].m_pname_alignment;
1655 const GLenum pname_max = s_buffer_infos[i].m_pname_max;
1656 const GLenum target = s_buffer_infos[i].m_target;
1657 const std::string& target_name = glu::getBufferTargetStr(target).toString();
1658
1659 GLintptr buffer_size = 16;
1660 GLsizei count = n_buffers;
1661 GLuint first = 0;
1662 GLuint invalid_id = 1; /* Start with 1, as 0 is not valid name */
1663 GLintptr offset = 4; /* ATOMIC and XFB require alignment of 4 */
1664 GLint offset_alignment = 1;
1665 GLint max_buffers = 0;
1666 GLintptr size = buffer_size - offset;
1667 size_t validated_index = n_buffers - 1;
1668
1669 /* Get alignment */
1670 if (0 != pname_alignment)
1671 {
1672 gl.getIntegerv(pname_alignment, &offset_alignment);
1673 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1674
1675 buffer_size += offset_alignment;
1676 offset = offset_alignment;
1677 size = buffer_size - offset;
1678 }
1679
1680 /* Get max */
1681 gl.getIntegerv(pname_max, &max_buffers);
1682 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1683
1684 /* Select count so <first + count> does not exceed max.
1685 * Validated index shall be in the specified range.
1686 */
1687 if (n_buffers > max_buffers)
1688 {
1689 count = max_buffers;
1690 validated_index = max_buffers - 1;
1691 }
1692
1693 /* Storage */
1694 Buffer buffer[n_buffers];
1695 GLuint buffer_ids[n_buffers];
1696 GLintptr offsets[n_buffers];
1697 GLintptr sizes[n_buffers];
1698
1699 /* Prepare buffers */
1700 for (size_t j = 0; j < n_buffers; ++j)
1701 {
1702 buffer[j].InitData(m_context, target, GL_DYNAMIC_COPY, buffer_size, 0 /* data */);
1703
1704 buffer_ids[j] = buffer[j].m_id;
1705 offsets[j] = offset;
1706 sizes[j] = size;
1707 }
1708
1709 /* - INVALID_OPERATION when <first> + <count> is greater than allowed limit; */
1710 {
1711 GLsizei t_count = n_buffers;
1712 GLuint t_first = 0;
1713
1714 /* Select first so <first + count> exceeds max, avoid negative first */
1715 if (n_buffers <= max_buffers)
1716 {
1717 t_first = max_buffers - n_buffers + 1;
1718 }
1719 else
1720 {
1721 t_count = max_buffers + 1;
1722 /* first = 0; */
1723 }
1724
1725 /* Test */
1726 gl.bindBuffersBase(target, t_first, t_count, buffer_ids);
1727 CHECK_ERROR(GL_INVALID_OPERATION,
1728 "BindBuffersBase with invalid <first> + <count>, target: " << target_name);
1729
1730 gl.bindBuffersRange(target, t_first, t_count, buffer_ids, offsets, sizes);
1731 CHECK_ERROR(GL_INVALID_OPERATION,
1732 "BindBuffersRange with invalid <first> + <count>, target: " << target_name);
1733 }
1734
1735 /* - INVALID_OPERATION if any value in <buffers> is not zero or the name of
1736 * existing buffer;
1737 */
1738 {
1739 GLuint t_buffer_ids[n_buffers];
1740
1741 memcpy(t_buffer_ids, buffer_ids, sizeof(buffer_ids));
1742
1743 /* Find invalid id */
1744 while (1)
1745 {
1746 if (GL_TRUE != gl.isBuffer(invalid_id))
1747 {
1748 break;
1749 }
1750
1751 invalid_id += 1;
1752 }
1753
1754 /* Invalidate the entry */
1755 t_buffer_ids[validated_index] = invalid_id;
1756
1757 /* Test */
1758 gl.bindBuffersBase(target, first, count, t_buffer_ids);
1759 CHECK_ERROR(GL_INVALID_OPERATION, "BindBuffersBase with invalid buffer id, target: " << target_name);
1760
1761 gl.bindBuffersRange(target, first, count, t_buffer_ids, offsets, sizes);
1762 CHECK_ERROR(GL_INVALID_OPERATION, "BindBuffersRange with invalid buffer id, target: " << target_name);
1763 }
1764
1765 /* - INVALID_VALUE if any value in <offsets> is less than zero; */
1766 {
1767 GLintptr t_offsets[n_buffers];
1768 GLintptr t_sizes[n_buffers];
1769
1770 memcpy(t_offsets, offsets, sizeof(offsets));
1771 memcpy(t_sizes, sizes, sizeof(sizes));
1772
1773 /* Invalidate the entry */
1774 t_offsets[validated_index] = -1;
1775 t_sizes[validated_index] = -1;
1776
1777 /* Test */
1778 gl.bindBuffersRange(target, first, count, buffer_ids, t_offsets, sizes);
1779 CHECK_ERROR(GL_INVALID_VALUE, "BindBuffersRange with negative offset, target: " << target_name);
1780
1781 /* Test */
1782 gl.bindBuffersRange(target, first, count, buffer_ids, offsets, t_sizes);
1783 CHECK_ERROR(GL_INVALID_VALUE, "BindBuffersRange with negative size, target: " << target_name);
1784 }
1785
1786 /* - INVALID_VALUE if any pair of <offsets> and <sizes> exceeds limits. */
1787 {
1788 GLintptr t_offsets[n_buffers];
1789 GLintptr t_sizes[n_buffers];
1790
1791 memcpy(t_offsets, offsets, sizeof(offsets));
1792 memcpy(t_sizes, sizes, sizeof(sizes));
1793
1794 /* Invalidate the entry */
1795 t_offsets[validated_index] -= 1; /* Not aligned by required value */
1796 t_sizes[validated_index] = size - 1; /* Not aligned by required value */
1797
1798 /* Test */
1799 gl.bindBuffersRange(target, first, count, buffer_ids, t_offsets, sizes);
1800 CHECK_ERROR(GL_INVALID_VALUE, "BindBuffersRange with invalid <offset>, target: " << target_name);
1801
1802 /* Test */
1803 if (GL_TRANSFORM_FEEDBACK_BUFFER == target)
1804 {
1805 gl.bindBuffersRange(target, first, count, buffer_ids, offsets, t_sizes);
1806 CHECK_ERROR(GL_INVALID_VALUE, "BindBuffersRange with invalid <size>, target: " << target_name);
1807 }
1808 }
1809 }
1810
1811 /* Set result */
1812 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1813
1814 /* Done */
1815 return tcu::TestNode::STOP;
1816 }
1817
1818 /** Constructor
1819 *
1820 * @param context Test context
1821 **/
ErrorsBindTexturesTest(deqp::Context & context)1822 ErrorsBindTexturesTest::ErrorsBindTexturesTest(deqp::Context& context)
1823 : TestCase(context, "errors_bind_textures", "Verifies that proper errors are generated by texture binding routines")
1824 {
1825 /* Nothing to be done */
1826 }
1827
1828 /** Execute test
1829 *
1830 * @return tcu::TestNode::STOP
1831 **/
iterate()1832 tcu::TestNode::IterateResult ErrorsBindTexturesTest::iterate()
1833 {
1834 static const GLuint depth = 8;
1835 static const GLuint height = 8;
1836 static const GLsizei n_textures = 4;
1837 static const GLuint width = 8;
1838
1839 const Functions& gl = m_context.getRenderContext().getFunctions();
1840
1841 #if DEBUG_ENBALE_MESSAGE_CALLBACK
1842 gl.debugMessageCallback(debug_proc, &m_context);
1843 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
1844 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
1845
1846 GLsizei count = n_textures;
1847 GLuint first = 0;
1848 GLuint invalid_id = 1; /* Start with 1, as 0 is not valid name */
1849 GLint max_textures = 0;
1850 size_t validated_index = n_textures - 1;
1851
1852 /* Get max */
1853 gl.getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_textures);
1854 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1855
1856 /* Select count so <first + count> does not exceed max.
1857 * Validated index shall be in the specified range.
1858 */
1859 if (n_textures > max_textures)
1860 {
1861 count = max_textures;
1862 validated_index = max_textures - 1;
1863 }
1864
1865 /* Storage */
1866 Texture texture[n_textures];
1867 GLuint texture_ids[n_textures];
1868
1869 /* Prepare textures */
1870 texture[0].InitStorage(m_context, GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, width, height, depth);
1871 texture[1].InitStorage(m_context, GL_TEXTURE_2D_ARRAY, 1 /* levels */, GL_RGBA8, width, height, depth);
1872 texture[2].InitStorage(m_context, GL_TEXTURE_1D_ARRAY, 1 /* levels */, GL_RGBA8, width, height, depth);
1873 texture[3].InitStorage(m_context, GL_TEXTURE_3D, 1 /* levels */, GL_RGBA8, width, height, depth);
1874
1875 for (size_t i = 0; i < n_textures; ++i)
1876 {
1877 texture_ids[i] = texture[i].m_id;
1878 }
1879
1880 /* - INVALID_OPERATION when <first> + <count> exceed limits; */
1881 {
1882 GLsizei t_count = n_textures;
1883 GLuint t_first = 0;
1884
1885 /* Select first so <first + count> exceeds max, avoid negative first */
1886 if (n_textures <= max_textures)
1887 {
1888 t_first = max_textures - n_textures + 1;
1889 }
1890 else
1891 {
1892 t_count = max_textures + 1;
1893 /* first = 0; */
1894 }
1895
1896 /* Test */
1897 gl.bindTextures(t_first, t_count, texture_ids);
1898 CHECK_ERROR(GL_INVALID_OPERATION, "BindTextures with invalid <first> + <count>");
1899 }
1900
1901 /* - INVALID_OPERATION if any value in <buffers> is not zero or the name of
1902 * existing buffer;
1903 */
1904 {
1905 GLuint t_texture_ids[n_textures];
1906
1907 memcpy(t_texture_ids, texture_ids, sizeof(texture_ids));
1908
1909 /* Find invalid id */
1910 while (1)
1911 {
1912 if (GL_TRUE != gl.isTexture(invalid_id))
1913 {
1914 break;
1915 }
1916
1917 invalid_id += 1;
1918 }
1919
1920 /* Invalidate the entry */
1921 t_texture_ids[validated_index] = invalid_id;
1922
1923 /* Test */
1924 gl.bindTextures(first, count, t_texture_ids);
1925 CHECK_ERROR(GL_INVALID_OPERATION, "BindTextures with invalid texture id");
1926 }
1927
1928 /* Set result */
1929 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1930
1931 /* Done */
1932 return tcu::TestNode::STOP;
1933 }
1934
1935 /** Constructor
1936 *
1937 * @param context Test context
1938 **/
ErrorsBindSamplersTest(deqp::Context & context)1939 ErrorsBindSamplersTest::ErrorsBindSamplersTest(deqp::Context& context)
1940 : TestCase(context, "errors_bind_samplers", "Verifies that proper errors are generated by sampler binding routines")
1941 {
1942 /* Nothing to be done */
1943 }
1944
1945 /** Execute test
1946 *
1947 * @return tcu::TestNode::STOP
1948 **/
iterate()1949 tcu::TestNode::IterateResult ErrorsBindSamplersTest::iterate()
1950 {
1951 static const GLsizei n_samplers = 4;
1952
1953 const Functions& gl = m_context.getRenderContext().getFunctions();
1954
1955 #if DEBUG_ENBALE_MESSAGE_CALLBACK
1956 gl.debugMessageCallback(debug_proc, &m_context);
1957 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
1958 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
1959
1960 GLsizei count = n_samplers;
1961 GLuint first = 0;
1962 GLuint invalid_id = 1; /* Start with 1, as 0 is not valid name */
1963 GLint max_samplers = 0;
1964 size_t validated_index = n_samplers - 1;
1965
1966 /* Get max */
1967 gl.getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_samplers);
1968 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1969
1970 /* Select count so <first + count> does not exceed max.
1971 * Validated index shall be in the specified range.
1972 */
1973 if (n_samplers > max_samplers)
1974 {
1975 count = max_samplers;
1976 validated_index = max_samplers - 1;
1977 }
1978
1979 /* Storage */
1980 GLuint sampler_ids[n_samplers];
1981
1982 /* Prepare samplers */
1983 gl.genSamplers(n_samplers, sampler_ids);
1984 GLU_EXPECT_NO_ERROR(gl.getError(), "GenSamplers");
1985
1986 try
1987 {
1988 /* - INVALID_OPERATION when <first> + <count> exceed limits; */
1989 {
1990 GLsizei t_count = n_samplers;
1991 GLuint t_first = 0;
1992
1993 /* Select first so <first + count> exceeds max, avoid negative first */
1994 if (n_samplers <= max_samplers)
1995 {
1996 t_first = max_samplers - n_samplers + 1;
1997 }
1998 else
1999 {
2000 t_count = max_samplers + 1;
2001 /* first = 0; */
2002 }
2003
2004 /* Test */
2005 gl.bindSamplers(t_first, t_count, sampler_ids);
2006 CHECK_ERROR(GL_INVALID_OPERATION, "BindSamplers with invalid <first> + <count>");
2007 }
2008
2009 /* - INVALID_OPERATION if any value in <buffers> is not zero or the name of
2010 * existing buffer;
2011 */
2012 {
2013 GLuint t_sampler_ids[n_samplers];
2014
2015 memcpy(t_sampler_ids, sampler_ids, sizeof(sampler_ids));
2016
2017 /* Find invalid id */
2018 while (1)
2019 {
2020 if (GL_TRUE != gl.isTexture(invalid_id))
2021 {
2022 break;
2023 }
2024
2025 invalid_id += 1;
2026 }
2027
2028 /* Invalidate the entry */
2029 t_sampler_ids[validated_index] = invalid_id;
2030
2031 /* Test */
2032 gl.bindTextures(first, count, t_sampler_ids);
2033 CHECK_ERROR(GL_INVALID_OPERATION, "BindSamplers with invalid sampler id");
2034 }
2035 }
2036 catch (const std::exception&)
2037 {
2038 gl.deleteSamplers(n_samplers, sampler_ids);
2039
2040 TCU_FAIL("Invalid error generated");
2041 }
2042
2043 /* Delete samplers */
2044 gl.deleteSamplers(n_samplers, sampler_ids);
2045
2046 /* Set result */
2047 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2048
2049 /* Done */
2050 return tcu::TestNode::STOP;
2051 }
2052
2053 /** Constructor
2054 *
2055 * @param context Test context
2056 **/
ErrorsBindImageTexturesTest(deqp::Context & context)2057 ErrorsBindImageTexturesTest::ErrorsBindImageTexturesTest(deqp::Context& context)
2058 : TestCase(context, "errors_bind_image_textures",
2059 "Verifies that proper errors are generated by image binding routines")
2060 {
2061 /* Nothing to be done */
2062 }
2063
2064 /** Execute test
2065 *
2066 * @return tcu::TestNode::STOP
2067 **/
iterate()2068 tcu::TestNode::IterateResult ErrorsBindImageTexturesTest::iterate()
2069 {
2070 static const GLuint depth = 8;
2071 static const GLuint height = 8;
2072 static const GLsizei n_textures = 4;
2073 static const GLuint width = 8;
2074
2075 const Functions& gl = m_context.getRenderContext().getFunctions();
2076
2077 #if DEBUG_ENBALE_MESSAGE_CALLBACK
2078 gl.debugMessageCallback(debug_proc, &m_context);
2079 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
2080 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
2081
2082 GLsizei count = n_textures;
2083 GLuint first = 0;
2084 GLuint invalid_id = 1; /* Start with 1, as 0 is not valid name */
2085 GLint max_textures = 0;
2086 size_t validated_index = n_textures - 1;
2087
2088 /* Get max */
2089 gl.getIntegerv(GL_MAX_IMAGE_UNITS, &max_textures);
2090 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2091
2092 /* Select count so <first + count> does not exceed max.
2093 * Validated index shall be in the specified range.
2094 */
2095 if (n_textures > max_textures)
2096 {
2097 count = max_textures;
2098 validated_index = max_textures - 1;
2099 }
2100
2101 /* Storage */
2102 Texture texture[n_textures];
2103 GLuint texture_ids[n_textures];
2104
2105 /* Prepare textures */
2106 texture[0].InitStorage(m_context, GL_TEXTURE_2D, 1, GL_RGBA8, width, height, depth);
2107 texture[1].InitStorage(m_context, GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, width, height, depth);
2108 texture[2].InitStorage(m_context, GL_TEXTURE_1D_ARRAY, 1, GL_RGBA8, width, height, depth);
2109 texture[3].InitStorage(m_context, GL_TEXTURE_3D, 1, GL_RGBA8, width, height, depth);
2110
2111 for (size_t i = 0; i < n_textures; ++i)
2112 {
2113 texture_ids[i] = texture[i].m_id;
2114 }
2115
2116 /* - INVALID_OPERATION when <first> + <count> exceed limits; */
2117 {
2118 GLsizei t_count = n_textures;
2119 GLuint t_first = 0;
2120
2121 /* Select first so <first + count> exceeds max, avoid negative first */
2122 if (n_textures <= max_textures)
2123 {
2124 t_first = max_textures - n_textures + 1;
2125 }
2126 else
2127 {
2128 t_count = max_textures + 1;
2129 /* first = 0; */
2130 }
2131
2132 /* Test */
2133 gl.bindImageTextures(t_first, t_count, texture_ids);
2134 CHECK_ERROR(GL_INVALID_OPERATION, "BindImageTextures with invalid <first> + <count>");
2135 }
2136
2137 /* - INVALID_OPERATION if any value in <buffers> is not zero or the name of
2138 * existing buffer;
2139 */
2140 {
2141 GLuint t_texture_ids[n_textures];
2142
2143 memcpy(t_texture_ids, texture_ids, sizeof(texture_ids));
2144
2145 /* Find invalid id */
2146 while (1)
2147 {
2148 if (GL_TRUE != gl.isTexture(invalid_id))
2149 {
2150 break;
2151 }
2152
2153 invalid_id += 1;
2154 }
2155
2156 /* Invalidate the entry */
2157 t_texture_ids[validated_index] = invalid_id;
2158
2159 /* Test */
2160 gl.bindImageTextures(first, count, t_texture_ids);
2161 CHECK_ERROR(GL_INVALID_OPERATION, "BindImageTextures with invalid texture id");
2162 }
2163
2164 /* - INVALID_OPERATION if any entry found in <textures> has invalid internal
2165 * format at level 0;
2166 */
2167 {
2168 GLuint t_texture_ids[n_textures];
2169
2170 memcpy(t_texture_ids, texture_ids, sizeof(texture_ids));
2171
2172 /* Prepare texture with invalid format */
2173 Texture t_texture;
2174 t_texture.Init(m_context);
2175 t_texture.Generate(gl, t_texture.m_id);
2176 t_texture.Bind(gl, t_texture.m_id, GL_TEXTURE_2D);
2177 gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGB9_E5, width, 0);
2178 CHECK_ERROR(GL_INVALID_VALUE, "texStorage2D has height set to 0");
2179
2180 /* Invalidate the entry */
2181 t_texture_ids[validated_index] = t_texture.m_id;
2182
2183 /* Test */
2184 gl.bindImageTextures(first, count, t_texture_ids);
2185 CHECK_ERROR(GL_INVALID_OPERATION, "BindImageTextures with invalid internal format");
2186 }
2187
2188 /* - INVALID_VALUE when any entry in <textures> has any of dimensions equal
2189 * to 0 at level 0.
2190 */
2191 {
2192 GLuint t_texture_ids[n_textures];
2193
2194 memcpy(t_texture_ids, texture_ids, sizeof(texture_ids));
2195
2196 /* Prepare texture with invalid format */
2197 Texture t_texture;
2198 t_texture.InitStorage(m_context, GL_TEXTURE_2D, 1, GL_RGB9_E5, width, 0, depth, true);
2199
2200 /* Invalidate the entry */
2201 t_texture_ids[validated_index] = t_texture.m_id;
2202
2203 /* Test */
2204 gl.bindImageTextures(first, count, t_texture_ids);
2205 CHECK_ERROR(GL_INVALID_VALUE, "BindImageTextures with 2D texture that has height set to 0");
2206 }
2207
2208 /* Set result */
2209 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2210
2211 /* Done */
2212 return tcu::TestNode::STOP;
2213 }
2214
2215 /** Constructor
2216 *
2217 * @param context Test context
2218 **/
ErrorsBindVertexBuffersTest(deqp::Context & context)2219 ErrorsBindVertexBuffersTest::ErrorsBindVertexBuffersTest(deqp::Context& context)
2220 : TestCase(context, "errors_bind_vertex_buffers",
2221 "Verifies that proper errors are generated by vertex buffer binding routines")
2222 {
2223 /* Nothing to be done */
2224 }
2225
2226 /** Execute test
2227 *
2228 * @return tcu::TestNode::STOP
2229 **/
iterate()2230 tcu::TestNode::IterateResult ErrorsBindVertexBuffersTest::iterate()
2231 {
2232 const Functions& gl = m_context.getRenderContext().getFunctions();
2233
2234 #if DEBUG_ENBALE_MESSAGE_CALLBACK
2235 gl.debugMessageCallback(debug_proc, &m_context);
2236 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
2237 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
2238
2239 static const GLsizei n_buffers = 4;
2240 static const GLsizei stride = 4;
2241
2242 GLintptr buffer_size = 16;
2243 GLsizei count = n_buffers;
2244 GLuint first = 0;
2245 GLuint invalid_id = 1; /* Start with 1, as 0 is not valid name */
2246 GLintptr offset = 4; /* ATOMIC and XFB require alignment of 4 */
2247 GLint max_buffers = 0;
2248 size_t validated_index = n_buffers - 1;
2249
2250 /* Get max */
2251 gl.getIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &max_buffers);
2252 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2253
2254 /* Select count so <first + count> does not exceed max.
2255 * Validated index shall be in the specified range.
2256 */
2257 if (n_buffers > max_buffers)
2258 {
2259 count = max_buffers;
2260 validated_index = max_buffers - 1;
2261 }
2262
2263 /* Storage */
2264 Buffer buffer[n_buffers];
2265 GLuint buffer_ids[n_buffers];
2266 GLintptr offsets[n_buffers];
2267 GLsizei strides[n_buffers];
2268
2269 /* Prepare buffers */
2270 for (size_t j = 0; j < n_buffers; ++j)
2271 {
2272 buffer[j].InitData(m_context, GL_ARRAY_BUFFER, GL_DYNAMIC_COPY, buffer_size, 0 /* data */);
2273
2274 buffer_ids[j] = buffer[j].m_id;
2275 offsets[j] = offset;
2276 strides[j] = stride;
2277 }
2278
2279 /* Prepare VAO */
2280 GLuint vao = 0;
2281 gl.genVertexArrays(1, &vao);
2282 GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
2283 try
2284 {
2285 gl.bindVertexArray(vao);
2286 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArrays");
2287
2288 /* - INVALID_OPERATION when <first> + <count> exceeds limits; */
2289 {
2290 GLsizei t_count = n_buffers;
2291 GLuint t_first = 0;
2292
2293 /* Select first so <first + count> exceeds max, avoid negative first */
2294 if (n_buffers <= max_buffers)
2295 {
2296 t_first = max_buffers - n_buffers + 1;
2297 }
2298 else
2299 {
2300 t_count = max_buffers + 1;
2301 /* first = 0; */
2302 }
2303
2304 /* Test */
2305 gl.bindVertexBuffers(t_first, t_count, buffer_ids, offsets, strides);
2306 CHECK_ERROR(GL_INVALID_OPERATION, "BindVertexBuffers with invalid <first> + <count>");
2307 }
2308
2309 /* - INVALID_OPERATION if any value in <buffers> is not zero or the name of
2310 * existing buffer;
2311 */
2312 {
2313 GLuint t_buffer_ids[n_buffers];
2314
2315 memcpy(t_buffer_ids, buffer_ids, sizeof(buffer_ids));
2316
2317 /* Find invalid id */
2318 while (1)
2319 {
2320 if (GL_TRUE != gl.isBuffer(invalid_id))
2321 {
2322 break;
2323 }
2324
2325 invalid_id += 1;
2326 }
2327
2328 /* Invalidate the entry */
2329 t_buffer_ids[validated_index] = invalid_id;
2330
2331 /* Test */
2332 gl.bindVertexBuffers(first, count, t_buffer_ids, offsets, strides);
2333 CHECK_ERROR(GL_INVALID_OPERATION, "BindVertexBuffers with invalid buffer id");
2334 }
2335
2336 /* - INVALID_VALUE if any value in <offsets> or <strides> is less than zero. */
2337 {
2338 GLintptr t_offsets[n_buffers];
2339 GLsizei t_strides[n_buffers];
2340
2341 memcpy(t_offsets, offsets, sizeof(offsets));
2342 memcpy(t_strides, strides, sizeof(strides));
2343
2344 /* Invalidate the entry */
2345 t_offsets[validated_index] = -1;
2346 t_strides[validated_index] = -1;
2347
2348 /* Test */
2349 gl.bindVertexBuffers(first, count, buffer_ids, t_offsets, strides);
2350 CHECK_ERROR(GL_INVALID_VALUE, "BindVertexBuffers with negative offset");
2351
2352 gl.bindVertexBuffers(first, count, buffer_ids, offsets, t_strides);
2353 CHECK_ERROR(GL_INVALID_VALUE, "BindVertexBuffers with negative stride");
2354 }
2355 }
2356 catch (const std::exception&)
2357 {
2358 gl.deleteVertexArrays(1, &vao);
2359 TCU_FAIL("Unexpected error generated");
2360 }
2361
2362 gl.deleteVertexArrays(1, &vao);
2363 GLU_EXPECT_NO_ERROR(gl.getError(), "DeleteVertexArrays");
2364
2365 /* Set result */
2366 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2367
2368 /* Done */
2369 return tcu::TestNode::STOP;
2370 }
2371
2372 /** Constructor
2373 *
2374 * @param context Test context
2375 **/
FunctionalBindBuffersBaseTest(deqp::Context & context)2376 FunctionalBindBuffersBaseTest::FunctionalBindBuffersBaseTest(deqp::Context& context)
2377 : TestCase(context, "functional_bind_buffers_base", "Verifies that BindBuffersBase works as expected")
2378 {
2379 /* Nothing to be done */
2380 }
2381
2382 /** Execute test
2383 *
2384 * @return tcu::TestNode::STOP
2385 **/
iterate()2386 tcu::TestNode::IterateResult FunctionalBindBuffersBaseTest::iterate()
2387 {
2388 const Functions& gl = m_context.getRenderContext().getFunctions();
2389
2390 #if DEBUG_ENBALE_MESSAGE_CALLBACK
2391 gl.debugMessageCallback(debug_proc, &m_context);
2392 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
2393 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
2394
2395 for (size_t i = 0; i < s_n_buffer_tragets; ++i)
2396 {
2397 const GLenum pname_binding = s_buffer_infos[i].m_pname_binding;
2398 const GLenum pname_max = s_buffer_infos[i].m_pname_max;
2399 const GLenum pname_max_size = s_buffer_infos[i].m_pname_max_size;
2400 const GLenum target = s_buffer_infos[i].m_target;
2401 const std::string& target_name = glu::getBufferTargetStr(target).toString();
2402
2403 GLint max_buffers = 0;
2404 GLint max_size = 0;
2405
2406 /* Get max */
2407 gl.getIntegerv(pname_max, &max_buffers);
2408 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2409
2410 /* Get max size */
2411 gl.getIntegerv(pname_max_size, &max_size);
2412 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2413
2414 GLintptr buffer_size = max_size / max_buffers;
2415
2416 /* Storage */
2417 std::vector<Buffer> buffer;
2418 std::vector<GLuint> buffer_ids;
2419
2420 buffer.resize(max_buffers);
2421 buffer_ids.resize(max_buffers);
2422
2423 /* Prepare buffers */
2424 for (GLint j = 0; j < max_buffers; ++j)
2425 {
2426 buffer[j].InitData(m_context, target, GL_DYNAMIC_COPY, buffer_size, 0 /* data */);
2427
2428 buffer_ids[j] = buffer[j].m_id;
2429 }
2430
2431 /*
2432 * - execute BindBufferBase to bind all buffers to tested target;
2433 * - inspect if bindings were modified;
2434 */
2435 gl.bindBuffersBase(target, 0 /* first */, max_buffers /* count */, &buffer_ids[0]);
2436 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersBase");
2437
2438 for (GLint j = 0; j < max_buffers; ++j)
2439 {
2440 checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]);
2441 }
2442
2443 /*
2444 *
2445 * - execute BindBufferBase for first half of bindings with NULL as <buffers>
2446 * to unbind first half of bindings for tested target;
2447 * - inspect if bindings were modified;
2448 * - execute BindBufferBase for second half of bindings with NULL as <buffers>
2449 * to unbind rest of bindings;
2450 * - inspect if bindings were modified;
2451 */
2452 GLint half_index = max_buffers / 2;
2453 gl.bindBuffersBase(target, 0 /* first */, half_index /* count */, 0);
2454 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersBase");
2455
2456 for (GLint j = 0; j < half_index; ++j)
2457 {
2458 checkBinding(m_context, pname_binding, j, target_name, 0);
2459 }
2460
2461 for (GLint j = half_index; j < max_buffers; ++j)
2462 {
2463 checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]);
2464 }
2465
2466 gl.bindBuffersBase(target, half_index /* first */, max_buffers - half_index /* count */, 0);
2467 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersBase");
2468
2469 for (GLint j = 0; j < max_buffers; ++j)
2470 {
2471 checkBinding(m_context, pname_binding, j, target_name, 0);
2472 }
2473
2474 /*
2475 * - change <buffers> so first entry is invalid;
2476 * - execute BindBufferBase to bind all buffers to tested target; It is
2477 * expected that INVALID_OPERATION will be generated;
2478 * - inspect if all bindings but first were modified;
2479 */
2480
2481 /* Find invalid id */
2482 GLuint invalid_id = 1;
2483 while (1)
2484 {
2485 if (GL_TRUE != gl.isBuffer(invalid_id))
2486 {
2487 break;
2488 }
2489
2490 invalid_id += 1;
2491 }
2492
2493 buffer_ids[0] = invalid_id;
2494
2495 gl.bindBuffersBase(target, 0 /* first */, max_buffers /* count */, &buffer_ids[0]);
2496 CHECK_ERROR(GL_INVALID_OPERATION, "BindBufferBase with invalid buffer id");
2497
2498 /* Update buffer_ids */
2499 buffer_ids[0] = 0; /* 0 means unbound */
2500
2501 for (GLint j = 0; j < max_buffers; ++j)
2502 {
2503 checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]);
2504 }
2505
2506 /*
2507 * - bind any buffer to first binding;
2508 * - execute BindBufferBase for 0 as <first>, 1 as <count> and <buffers> filled
2509 * with zeros to unbind 1st binding for tested target;
2510 * - inspect if bindings were modified;
2511 */
2512 gl.bindBufferBase(target, 0, buffer[0].m_id);
2513 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferBase");
2514 checkBinding(m_context, pname_binding, 0, target_name, buffer[0].m_id);
2515
2516 std::vector<GLuint> t_buffer_ids;
2517 t_buffer_ids.resize(max_buffers);
2518
2519 gl.bindBuffersBase(target, 0 /* first */, 1 /* count */, &t_buffer_ids[0]);
2520 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersBase");
2521
2522 for (GLint j = 0; j < max_buffers; ++j)
2523 {
2524 checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]);
2525 }
2526
2527 /* - unbind all buffers. */
2528 gl.bindBuffersBase(target, 0 /* first */, max_buffers /* count */, 0);
2529 }
2530
2531 /* Set result */
2532 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2533
2534 /* Done */
2535 return tcu::TestNode::STOP;
2536 }
2537
2538 /** Constructor
2539 *
2540 * @param context Test context
2541 **/
FunctionalBindBuffersRangeTest(deqp::Context & context)2542 FunctionalBindBuffersRangeTest::FunctionalBindBuffersRangeTest(deqp::Context& context)
2543 : TestCase(context, "functional_bind_buffers_range", "Verifies that BindBuffersRange works as expected")
2544 {
2545 /* Nothing to be done */
2546 }
2547
2548 /** Execute test
2549 *
2550 * @return tcu::TestNode::STOP
2551 **/
iterate()2552 tcu::TestNode::IterateResult FunctionalBindBuffersRangeTest::iterate()
2553 {
2554 const Functions& gl = m_context.getRenderContext().getFunctions();
2555
2556 #if DEBUG_ENBALE_MESSAGE_CALLBACK
2557 gl.debugMessageCallback(debug_proc, &m_context);
2558 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
2559 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
2560
2561 for (size_t i = 0; i < s_n_buffer_tragets; ++i)
2562 {
2563 const GLenum pname_binding = s_buffer_infos[i].m_pname_binding;
2564 const GLenum pname_max = s_buffer_infos[i].m_pname_max;
2565 const GLenum pname_max_size = s_buffer_infos[i].m_pname_max_size;
2566 const GLenum target = s_buffer_infos[i].m_target;
2567 const std::string& target_name = glu::getBufferTargetStr(target).toString();
2568
2569 GLint max_buffers = 0;
2570 GLint max_size = 0;
2571
2572 /* Get max */
2573 gl.getIntegerv(pname_max, &max_buffers);
2574 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2575
2576 /* Get max size */
2577 gl.getIntegerv(pname_max_size, &max_size);
2578 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2579
2580 GLintptr buffer_size = max_size / max_buffers;
2581
2582 /* Storage */
2583 std::vector<Buffer> buffer;
2584 std::vector<GLuint> buffer_ids;
2585 std::vector<GLintptr> offsets;
2586 std::vector<GLsizeiptr> sizes;
2587
2588 buffer.resize(max_buffers);
2589 buffer_ids.resize(max_buffers);
2590 offsets.resize(max_buffers);
2591 sizes.resize(max_buffers);
2592
2593 /* Prepare buffers */
2594 for (GLint j = 0; j < max_buffers; ++j)
2595 {
2596 buffer[j].InitData(m_context, target, GL_DYNAMIC_COPY, buffer_size, 0 /* data */);
2597
2598 buffer_ids[j] = buffer[j].m_id;
2599 offsets[j] = 0;
2600 sizes[j] = buffer_size;
2601 }
2602
2603 /*
2604 * - execute BindBufferBase to bind all buffers to tested target;
2605 * - inspect if bindings were modified;
2606 */
2607 gl.bindBuffersRange(target, 0 /* first */, max_buffers /* count */, &buffer_ids[0], &offsets[0], &sizes[0]);
2608 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersRange");
2609
2610 for (GLint j = 0; j < max_buffers; ++j)
2611 {
2612 checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]);
2613 }
2614
2615 /*
2616 *
2617 * - execute BindBufferBase for first half of bindings with NULL as <buffers>
2618 * to unbind first half of bindings for tested target;
2619 * - inspect if bindings were modified;
2620 * - execute BindBufferBase for second half of bindings with NULL as <buffers>
2621 * to unbind rest of bindings;
2622 * - inspect if bindings were modified;
2623 */
2624 GLint half_index = max_buffers / 2;
2625 gl.bindBuffersRange(target, 0 /* first */, half_index /* count */, 0, &offsets[0], &sizes[0]);
2626 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersRange");
2627
2628 for (GLint j = 0; j < half_index; ++j)
2629 {
2630 checkBinding(m_context, pname_binding, j, target_name, 0);
2631 }
2632
2633 for (GLint j = half_index; j < max_buffers; ++j)
2634 {
2635 checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]);
2636 }
2637
2638 gl.bindBuffersRange(target, half_index /* first */, max_buffers - half_index /* count */, 0, &offsets[0],
2639 &sizes[0]);
2640 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersRange");
2641
2642 for (GLint j = 0; j < max_buffers; ++j)
2643 {
2644 checkBinding(m_context, pname_binding, j, target_name, 0);
2645 }
2646
2647 /*
2648 * - change <buffers> so first entry is invalid;
2649 * - execute BindBufferBase to bind all buffers to tested target; It is
2650 * expected that INVALID_OPERATION will be generated;
2651 * - inspect if all bindings but first were modified;
2652 */
2653
2654 /* Find invalid id */
2655 GLuint invalid_id = 1;
2656 while (1)
2657 {
2658 if (GL_TRUE != gl.isBuffer(invalid_id))
2659 {
2660 break;
2661 }
2662
2663 invalid_id += 1;
2664 }
2665
2666 buffer_ids[0] = invalid_id;
2667
2668 gl.bindBuffersRange(target, 0 /* first */, max_buffers /* count */, &buffer_ids[0], &offsets[0], &sizes[0]);
2669 CHECK_ERROR(GL_INVALID_OPERATION, "BindBuffersRange with invalid buffer id");
2670
2671 /* Update buffer_ids */
2672 buffer_ids[0] = 0; /* 0 means unbound */
2673
2674 for (GLint j = 0; j < max_buffers; ++j)
2675 {
2676 checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]);
2677 }
2678
2679 /*
2680 * - bind any buffer to first binding;
2681 * - execute BindBufferBase for 0 as <first>, 1 as <count> and <buffers> filled
2682 * with zeros to unbind 1st binding for tested target;
2683 * - inspect if bindings were modified;
2684 */
2685 gl.bindBufferBase(target, 0, buffer[0].m_id);
2686 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferBase");
2687 checkBinding(m_context, pname_binding, 0, target_name, buffer[0].m_id);
2688
2689 std::vector<GLuint> t_buffer_ids;
2690 t_buffer_ids.resize(max_buffers);
2691
2692 gl.bindBuffersRange(target, 0 /* first */, 1 /* count */, &t_buffer_ids[0], &offsets[0], &sizes[0]);
2693 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersRange");
2694
2695 for (GLint j = 0; j < max_buffers; ++j)
2696 {
2697 checkBinding(m_context, pname_binding, j, target_name, buffer_ids[j]);
2698 }
2699
2700 /* - unbind all buffers. */
2701 gl.bindBuffersBase(target, 0 /* first */, max_buffers /* count */, 0);
2702 }
2703
2704 /* Set result */
2705 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2706
2707 /* Done */
2708 return tcu::TestNode::STOP;
2709 }
2710
2711 /** Constructor
2712 *
2713 * @param context Test context
2714 **/
FunctionalBindTexturesTest(deqp::Context & context)2715 FunctionalBindTexturesTest::FunctionalBindTexturesTest(deqp::Context& context)
2716 : TestCase(context, "functional_bind_textures", "Verifies that BindTextures works as expected")
2717 {
2718 /* Nothing to be done */
2719 }
2720
2721 /** Execute test
2722 *
2723 * @return tcu::TestNode::STOP
2724 **/
iterate()2725 tcu::TestNode::IterateResult FunctionalBindTexturesTest::iterate()
2726 {
2727 static const GLuint depth = 6;
2728 static const GLuint height = 6;
2729 static const GLuint width = 6;
2730
2731 const Functions& gl = m_context.getRenderContext().getFunctions();
2732
2733 #if DEBUG_ENBALE_MESSAGE_CALLBACK
2734 gl.debugMessageCallback(debug_proc, &m_context);
2735 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
2736 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
2737
2738 GLuint invalid_id = 1; /* Start with 1, as 0 is not valid name */
2739 GLint max_textures = 0;
2740
2741 /* Get max */
2742 gl.getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_textures);
2743 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2744
2745 /* Storage */
2746 Buffer buffer;
2747 std::vector<Texture> texture;
2748 std::vector<GLuint> texture_ids;
2749 std::vector<GLuint> t_texture_ids;
2750
2751 texture.resize(max_textures);
2752 texture_ids.resize(max_textures);
2753 t_texture_ids.resize(max_textures);
2754
2755 /* Prepare buffer */
2756 buffer.InitData(m_context, GL_TEXTURE_BUFFER, GL_DYNAMIC_COPY, 16 /* size */, 0 /* data */);
2757
2758 /* Prepare textures */
2759 for (size_t i = 0; i < s_n_texture_tragets; ++i)
2760 {
2761 const GLenum target = s_texture_infos[i].m_target;
2762
2763 if (GL_TEXTURE_BUFFER != target)
2764 {
2765 texture[i].InitStorage(m_context, target, 1, GL_RGBA8, width, height, depth);
2766 }
2767 else
2768 {
2769 texture[i].InitBuffer(m_context, GL_RGBA8, buffer.m_id);
2770 }
2771
2772 /* Unbind */
2773 Texture::Bind(gl, 0, target);
2774 }
2775
2776 for (GLint i = s_n_texture_tragets; i < max_textures; ++i)
2777 {
2778 texture[i].InitStorage(m_context, GL_TEXTURE_2D, 1, GL_RGBA8, width, height, depth);
2779 }
2780
2781 /* Unbind */
2782 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2783
2784 for (GLint i = 0; i < max_textures; ++i)
2785 {
2786 texture_ids[i] = texture[i].m_id;
2787 }
2788
2789 /*
2790 * - execute BindTextures to bind all textures;
2791 * - inspect bindings of all texture units to verify that proper bindings were
2792 * set;
2793 */
2794 gl.bindTextures(0, max_textures, &texture_ids[0]);
2795 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTextures");
2796
2797 for (GLint i = 0; i < max_textures; ++i)
2798 {
2799 checkTextureBinding(m_context, getBinding(i), i, texture_ids[i]);
2800 }
2801
2802 /*
2803 * - execute BindTextures for the first half of units with <textures> filled
2804 * with zeros, to unbind those units;
2805 * - inspect bindings of all texture units to verify that proper bindings were
2806 * unbound;
2807 */
2808 GLint half_index = max_textures / 2;
2809
2810 for (GLint i = 0; i < max_textures; ++i)
2811 {
2812 t_texture_ids[i] = 0;
2813 }
2814
2815 gl.bindTextures(0, half_index, &t_texture_ids[0]);
2816 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTextures");
2817
2818 for (GLint i = 0; i < half_index; ++i)
2819 {
2820 checkTextureBinding(m_context, getBinding(i), i, 0);
2821 }
2822
2823 for (GLint i = half_index; i < max_textures; ++i)
2824 {
2825 checkTextureBinding(m_context, getBinding(i), i, texture_ids[i]);
2826 }
2827
2828 /*
2829 * - execute BindTextures for the second half of units with NULL as<textures>,
2830 * to unbind those units;
2831 * - inspect bindings of all texture units to verify that proper bindings were
2832 * unbound;
2833 */
2834 gl.bindTextures(half_index, max_textures - half_index, 0);
2835 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTextures");
2836
2837 for (GLint i = 0; i < max_textures; ++i)
2838 {
2839 checkTextureBinding(m_context, getBinding(i), i, 0);
2840 }
2841
2842 /*
2843 * - modify <textures> so first entry is invalid;
2844 * - execute BindTextures to bind all textures; It is expected that
2845 * INVALID_OPERATION will be generated;
2846 * - inspect bindings of all texture units to verify that proper bindings were
2847 * set;
2848 */
2849
2850 /* Find invalid id */
2851 while (1)
2852 {
2853 if (GL_TRUE != gl.isTexture(invalid_id))
2854 {
2855 break;
2856 }
2857
2858 invalid_id += 1;
2859 }
2860
2861 /* Set invalid id */
2862 texture_ids[0] = invalid_id;
2863
2864 gl.bindTextures(0, max_textures, &texture_ids[0]);
2865 CHECK_ERROR(GL_INVALID_OPERATION, "BindTextures with invalid texture id");
2866
2867 checkTextureBinding(m_context, getBinding(0), 0, 0);
2868 for (GLint i = 1; i < max_textures; ++i)
2869 {
2870 checkTextureBinding(m_context, getBinding(i), i, texture_ids[i]);
2871 }
2872
2873 /* - unbind all textures. */
2874 gl.bindTextures(0, max_textures, 0);
2875 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTextures");
2876
2877 /* Set result */
2878 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2879
2880 /* Done */
2881 return tcu::TestNode::STOP;
2882 }
2883
2884 /** Constructor
2885 *
2886 * @param context Test context
2887 **/
FunctionalBindSamplersTest(deqp::Context & context)2888 FunctionalBindSamplersTest::FunctionalBindSamplersTest(deqp::Context& context)
2889 : TestCase(context, "functional_bind_samplers", "Verifies that BindSamplers works as expected")
2890 {
2891 /* Nothing to be done */
2892 }
2893
2894 /** Execute test
2895 *
2896 * @return tcu::TestNode::STOP
2897 **/
iterate()2898 tcu::TestNode::IterateResult FunctionalBindSamplersTest::iterate()
2899 {
2900 const Functions& gl = m_context.getRenderContext().getFunctions();
2901
2902 #if DEBUG_ENBALE_MESSAGE_CALLBACK
2903 gl.debugMessageCallback(debug_proc, &m_context);
2904 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
2905 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
2906
2907 GLuint invalid_id = 1; /* Start with 1, as 0 is not valid name */
2908 GLint max_samplers = 0;
2909
2910 /* Get max */
2911 gl.getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_samplers);
2912 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2913
2914 /* Storage */
2915 std::vector<GLuint> sampler_ids;
2916 std::vector<GLuint> t_sampler_ids;
2917
2918 sampler_ids.resize(max_samplers);
2919 t_sampler_ids.resize(max_samplers);
2920
2921 for (GLint i = 0; i < max_samplers; ++i)
2922 {
2923 t_sampler_ids[i] = 0;
2924 }
2925
2926 /* Prepare samplers */
2927 gl.genSamplers(max_samplers, &sampler_ids[0]);
2928 GLU_EXPECT_NO_ERROR(gl.getError(), "GenSamplers");
2929
2930 try
2931 {
2932 /* - execute BindSamplers to bind all samplers;
2933 * - inspect bindings to verify that proper samplers were set;
2934 */
2935 gl.bindSamplers(0 /* first */, max_samplers /* count */, &sampler_ids[0]);
2936 GLU_EXPECT_NO_ERROR(gl.getError(), "BindSamplers");
2937
2938 for (GLint i = 0; i < max_samplers; ++i)
2939 {
2940 checkBinding(m_context, GL_SAMPLER_BINDING, i, "Sampler", sampler_ids[i]);
2941 }
2942
2943 /* - execute BindSamplers for first half of bindings with <samplers> filled
2944 * with zeros, to unbind those samplers;
2945 * - inspect bindings to verify that proper samplers were unbound;
2946 */
2947 GLint half_index = max_samplers / 2;
2948
2949 gl.bindSamplers(0, half_index, &t_sampler_ids[0]);
2950 GLU_EXPECT_NO_ERROR(gl.getError(), "BindSamplers");
2951
2952 for (GLint i = 0; i < half_index; ++i)
2953 {
2954 checkBinding(m_context, GL_SAMPLER_BINDING, i, "Sampler", 0);
2955 }
2956
2957 for (GLint i = half_index; i < max_samplers; ++i)
2958 {
2959 checkBinding(m_context, GL_SAMPLER_BINDING, i, "Sampler", sampler_ids[i]);
2960 }
2961
2962 /* - execute BindSamplers for second half of bindings with NULL as <samplers>,
2963 * to unbind those samplers;
2964 * - inspect bindings to verify that proper samplers were unbound;
2965 */
2966 gl.bindSamplers(half_index, max_samplers - half_index, 0);
2967 GLU_EXPECT_NO_ERROR(gl.getError(), "BindSamplers");
2968
2969 for (GLint i = 0; i < max_samplers; ++i)
2970 {
2971 checkBinding(m_context, GL_SAMPLER_BINDING, i, "Sampler", 0);
2972 }
2973
2974 /* - modify <samplers> so first entry is invalid;
2975 * - execute BindSamplers to bind all samplers; It is expected that
2976 * INVALID_OPERATION will be generated;
2977 * - inspect bindings to verify that proper samplers were set;
2978 */
2979
2980 /* Find invalid id */
2981 while (1)
2982 {
2983 if (GL_TRUE != gl.isSampler(invalid_id))
2984 {
2985 break;
2986 }
2987
2988 invalid_id += 1;
2989 }
2990
2991 /* Prepare ids */
2992 t_sampler_ids[0] = invalid_id;
2993
2994 for (GLint i = 1; i < max_samplers; ++i)
2995 {
2996 t_sampler_ids[i] = sampler_ids[i];
2997 }
2998
2999 /* Bind */
3000 gl.bindSamplers(0, max_samplers, &t_sampler_ids[0]);
3001 CHECK_ERROR(GL_INVALID_OPERATION, "BindSamplers with invalid sampler id");
3002
3003 /* Set 0 for invalid entry */
3004 t_sampler_ids[0] = 0;
3005
3006 for (GLint i = 0; i < max_samplers; ++i)
3007 {
3008 checkBinding(m_context, GL_SAMPLER_BINDING, i, "Sampler", t_sampler_ids[i]);
3009 }
3010
3011 /* - unbind all samplers. */
3012 gl.bindSamplers(0, max_samplers, 0);
3013 GLU_EXPECT_NO_ERROR(gl.getError(), "BindSamplers");
3014 }
3015 catch (const std::exception&)
3016 {
3017 gl.deleteSamplers(max_samplers, &sampler_ids[0]);
3018
3019 TCU_FAIL("Invalid error generated");
3020 }
3021
3022 /* Delete samplers */
3023 gl.deleteSamplers(max_samplers, &sampler_ids[0]);
3024
3025 /* Set result */
3026 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3027
3028 /* Done */
3029 return tcu::TestNode::STOP;
3030 }
3031
3032 /** Constructor
3033 *
3034 * @param context Test context
3035 **/
FunctionalBindImageTexturesTest(deqp::Context & context)3036 FunctionalBindImageTexturesTest::FunctionalBindImageTexturesTest(deqp::Context& context)
3037 : TestCase(context, "functional_bind_image_textures", "Verifies that BindImageTextures works as expected")
3038 {
3039 /* Nothing to be done */
3040 }
3041
3042 /** Execute test
3043 *
3044 * @return tcu::TestNode::STOP
3045 **/
iterate()3046 tcu::TestNode::IterateResult FunctionalBindImageTexturesTest::iterate()
3047 {
3048 static const GLuint depth = 6;
3049 static const GLuint height = 6;
3050 static const GLuint width = 6;
3051
3052 const Functions& gl = m_context.getRenderContext().getFunctions();
3053
3054 #if DEBUG_ENBALE_MESSAGE_CALLBACK
3055 gl.debugMessageCallback(debug_proc, &m_context);
3056 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
3057 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
3058
3059 GLuint invalid_id = 1; /* Start with 1, as 0 is not valid name */
3060 GLint max_textures = 0;
3061
3062 /* Get max */
3063 gl.getIntegerv(GL_MAX_IMAGE_UNITS, &max_textures);
3064 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3065
3066 /* Storage */
3067 Buffer buffer;
3068 std::vector<Texture> texture;
3069 std::vector<GLuint> texture_ids;
3070 std::vector<GLuint> t_texture_ids;
3071
3072 texture.resize(max_textures);
3073 texture_ids.resize(max_textures);
3074 t_texture_ids.resize(max_textures);
3075
3076 /* Prepare buffer */
3077 buffer.InitData(m_context, GL_TEXTURE_BUFFER, GL_DYNAMIC_COPY, 16 /* size */, 0 /* data */);
3078
3079 /* Prepare textures */
3080 for (GLint i = 0; i < (GLint)s_n_texture_tragets; ++i)
3081 {
3082 const GLenum target = s_texture_infos[i].m_target;
3083
3084 if (i >= max_textures)
3085 {
3086 break;
3087 }
3088
3089 if (GL_TEXTURE_BUFFER != target)
3090 {
3091 texture[i].InitStorage(m_context, target, 1, GL_RGBA8, width, height, depth);
3092 }
3093 else
3094 {
3095 texture[i].InitBuffer(m_context, GL_RGBA8, buffer.m_id);
3096 }
3097
3098 /* Unbind */
3099 Texture::Bind(gl, 0, target);
3100 }
3101
3102 for (GLint i = (GLint)s_n_texture_tragets; i < max_textures; ++i)
3103 {
3104 texture[i].InitStorage(m_context, GL_TEXTURE_2D, 1, GL_RGBA8, width, height, depth);
3105 }
3106
3107 /* Unbind */
3108 Texture::Bind(gl, 0, GL_TEXTURE_2D);
3109
3110 for (GLint i = 0; i < max_textures; ++i)
3111 {
3112 texture_ids[i] = texture[i].m_id;
3113 }
3114
3115 /*
3116 * - execute BindImageTextures to bind all images;
3117 * - inspect bindings to verify that proper images were set;
3118 */
3119 gl.bindImageTextures(0, max_textures, &texture_ids[0]);
3120 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTextures");
3121
3122 for (GLint i = 0; i < max_textures; ++i)
3123 {
3124 checkBinding(m_context, GL_IMAGE_BINDING_NAME, i, "Image unit", texture_ids[i]);
3125 }
3126
3127 /*
3128 * - execute BindTextures for the first half of units with <textures> filled
3129 * with zeros, to unbind those units;
3130 * - inspect bindings of all texture units to verify that proper bindings were
3131 * unbound;
3132 */
3133 GLint half_index = max_textures / 2;
3134
3135 for (GLint i = 0; i < max_textures; ++i)
3136 {
3137 t_texture_ids[i] = 0;
3138 }
3139
3140 gl.bindImageTextures(0, half_index, &t_texture_ids[0]);
3141 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTextures");
3142
3143 for (GLint i = 0; i < half_index; ++i)
3144 {
3145 checkBinding(m_context, GL_IMAGE_BINDING_NAME, i, "Image unit", 0);
3146 }
3147
3148 for (GLint i = half_index; i < max_textures; ++i)
3149 {
3150 checkBinding(m_context, GL_IMAGE_BINDING_NAME, i, "Image unit", texture_ids[i]);
3151 }
3152
3153 /*
3154 * - execute BindTextures for the second half of units with NULL as<textures>,
3155 * to unbind those units;
3156 * - inspect bindings of all texture units to verify that proper bindings were
3157 * unbound;
3158 */
3159 gl.bindImageTextures(half_index, max_textures - half_index, 0);
3160 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTextures");
3161
3162 for (GLint i = 0; i < max_textures; ++i)
3163 {
3164 checkBinding(m_context, GL_IMAGE_BINDING_NAME, i, "Image unit", 0);
3165 }
3166
3167 /*
3168 * - modify <textures> so first entry is invalid;
3169 * - execute BindTextures to bind all textures; It is expected that
3170 * INVALID_OPERATION will be generated;
3171 * - inspect bindings of all texture units to verify that proper bindings were
3172 * set;
3173 */
3174
3175 /* Find invalid id */
3176 while (1)
3177 {
3178 if (GL_TRUE != gl.isTexture(invalid_id))
3179 {
3180 break;
3181 }
3182
3183 invalid_id += 1;
3184 }
3185
3186 /* Set invalid id */
3187 texture_ids[0] = invalid_id;
3188
3189 gl.bindImageTextures(0, max_textures, &texture_ids[0]);
3190 CHECK_ERROR(GL_INVALID_OPERATION, "BindImageTextures with invalid texture id");
3191
3192 checkBinding(m_context, GL_IMAGE_BINDING_NAME, 0, "Image unit", 0);
3193 for (GLint i = 1; i < max_textures; ++i)
3194 {
3195 checkBinding(m_context, GL_IMAGE_BINDING_NAME, i, "Image unit", texture_ids[i]);
3196 }
3197
3198 /* - unbind all textures. */
3199 gl.bindImageTextures(0, max_textures, 0);
3200 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTextures");
3201
3202 /* Set result */
3203 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3204
3205 /* Done */
3206 return tcu::TestNode::STOP;
3207 }
3208
3209 /** Constructor
3210 *
3211 * @param context Test context
3212 **/
FunctionalBindVertexBuffersTest(deqp::Context & context)3213 FunctionalBindVertexBuffersTest::FunctionalBindVertexBuffersTest(deqp::Context& context)
3214 : TestCase(context, "functional_bind_vertex_buffers", "Verifies that BindVertexBuffers works as expected")
3215 {
3216 /* Nothing to be done */
3217 }
3218
3219 /** Execute test
3220 *
3221 * @return tcu::TestNode::STOP
3222 **/
iterate()3223 tcu::TestNode::IterateResult FunctionalBindVertexBuffersTest::iterate()
3224 {
3225 const Functions& gl = m_context.getRenderContext().getFunctions();
3226
3227 #if DEBUG_ENBALE_MESSAGE_CALLBACK
3228 gl.debugMessageCallback(debug_proc, &m_context);
3229 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
3230 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
3231
3232 static const GLintptr buffer_size = 16;
3233 static const GLintptr offset = 4;
3234 static const GLsizei stride = 4;
3235
3236 GLuint invalid_id = 1; /* Start with 1, as 0 is not valid name */
3237 GLint max_buffers = 0;
3238
3239 /* Get max */
3240 gl.getIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &max_buffers);
3241 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3242
3243 /* Storage */
3244 std::vector<Buffer> buffer;
3245 std::vector<GLuint> buffer_ids;
3246 std::vector<GLintptr> offsets;
3247 std::vector<GLsizei> strides;
3248 std::vector<GLuint> t_buffer_ids;
3249
3250 buffer.resize(max_buffers);
3251 buffer_ids.resize(max_buffers);
3252 offsets.resize(max_buffers);
3253 strides.resize(max_buffers);
3254 t_buffer_ids.resize(max_buffers);
3255
3256 /* Prepare buffers */
3257 for (GLint i = 0; i < max_buffers; ++i)
3258 {
3259 buffer[i].InitData(m_context, GL_ARRAY_BUFFER, GL_DYNAMIC_COPY, buffer_size, 0 /* data */);
3260
3261 buffer_ids[i] = buffer[i].m_id;
3262 offsets[i] = offset;
3263 strides[i] = stride;
3264 t_buffer_ids[i] = 0;
3265 }
3266
3267 GLuint vao = 0;
3268 gl.genVertexArrays(1, &vao);
3269 GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
3270 try
3271 {
3272 gl.bindVertexArray(vao);
3273 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArrays");
3274
3275 /* - execute BindVertexBuffers to bind all buffer;
3276 * - inspect bindings to verify that proper buffers were set;
3277 */
3278 gl.bindVertexBuffers(0, max_buffers, &buffer_ids[0], &offsets[0], &strides[0]);
3279 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexBuffers");
3280
3281 for (GLint i = 0; i < max_buffers; ++i)
3282 {
3283 checkVertexAttribBinding(m_context, i, buffer_ids[i]);
3284 }
3285
3286 /* - execute BindVertexBuffers for first half of bindings with <buffers> filled
3287 * with zeros, to unbind those buffers;
3288 * - inspect bindings to verify that proper buffers were unbound;
3289 */
3290 GLint half_index = max_buffers / 2;
3291
3292 gl.bindVertexBuffers(0, half_index, &t_buffer_ids[0], &offsets[0], &strides[0]);
3293 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexBuffers");
3294
3295 for (GLint i = 0; i < half_index; ++i)
3296 {
3297 checkVertexAttribBinding(m_context, i, 0);
3298 }
3299
3300 for (GLint i = half_index; i < max_buffers; ++i)
3301 {
3302 checkVertexAttribBinding(m_context, i, buffer_ids[i]);
3303 }
3304
3305 /* - execute BindVertexBuffers for second half of bindings with NULL as
3306 * <buffers>, to unbind those buffers;
3307 * - inspect bindings to verify that proper buffers were unbound;
3308 */
3309 gl.bindVertexBuffers(half_index, max_buffers - half_index, 0, &offsets[0], &strides[0]);
3310 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexBuffers");
3311
3312 for (GLint i = 0; i < max_buffers; ++i)
3313 {
3314 checkVertexAttribBinding(m_context, i, 0);
3315 }
3316
3317 /* - modify <buffers> so first entry is invalid;
3318 * - execute BindVertexBuffers to bind all buffers; It is expected that
3319 * INVALID_OPERATION will be generated;
3320 * - inspect bindings to verify that proper buffers were set;
3321 */
3322
3323 /* Find invalid id */
3324 while (1)
3325 {
3326 if (GL_TRUE != gl.isBuffer(invalid_id))
3327 {
3328 break;
3329 }
3330
3331 invalid_id += 1;
3332 }
3333
3334 buffer_ids[0] = invalid_id;
3335 gl.bindVertexBuffers(0, max_buffers, &buffer_ids[0], &offsets[0], &strides[0]);
3336 CHECK_ERROR(GL_INVALID_OPERATION, "BindVertexBuffers with invalid id");
3337
3338 checkVertexAttribBinding(m_context, 0, 0);
3339 for (GLint i = 1; i < max_buffers; ++i)
3340 {
3341 checkVertexAttribBinding(m_context, i, buffer_ids[i]);
3342 }
3343
3344 /* - unbind all buffers. */
3345 gl.bindVertexBuffers(0, max_buffers, 0, &offsets[0], &strides[0]);
3346 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexBuffers");
3347 }
3348 catch (const std::exception&)
3349 {
3350 gl.deleteVertexArrays(1, &vao);
3351
3352 TCU_FAIL("Unexpected error generated");
3353 }
3354
3355 gl.deleteVertexArrays(1, &vao);
3356 GLU_EXPECT_NO_ERROR(gl.getError(), "DeleteVertexArrays");
3357
3358 /* Set result */
3359 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3360
3361 /* Done */
3362 return tcu::TestNode::STOP;
3363 }
3364
3365 /** Constructor
3366 *
3367 * @param context Test context
3368 **/
DispatchBindBuffersBaseTest(deqp::Context & context)3369 DispatchBindBuffersBaseTest::DispatchBindBuffersBaseTest(deqp::Context& context)
3370 : TestCase(context, "dispatch_bind_buffers_base", "Tests BindBuffersBase with dispatch command")
3371 {
3372 /* Nothing to be done */
3373 }
3374
3375 /** Execute test
3376 *
3377 * @return tcu::TestNode::STOP
3378 **/
iterate()3379 tcu::TestNode::IterateResult DispatchBindBuffersBaseTest::iterate()
3380 {
3381 static const GLchar* cs = "#version 440 core\n"
3382 "\n"
3383 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
3384 "\n"
3385 "UBO_LIST\n"
3386 "layout (std140, binding = 0) buffer SSB {\n"
3387 " vec4 sum;\n"
3388 "} ssb;\n"
3389 "\n"
3390 "void main()\n"
3391 "{\n"
3392 " ssb.sum = SUM_LIST;\n"
3393 "}\n"
3394 "\n";
3395
3396 static const GLchar* ubo = "layout (std140, binding = XXX) uniform BXXX { vec4 data; } bXXX;";
3397
3398 static const GLintptr buffer_size = 4 * sizeof(GLfloat);
3399
3400 const Functions& gl = m_context.getRenderContext().getFunctions();
3401
3402 bool test_result = true;
3403
3404 #if DEBUG_ENBALE_MESSAGE_CALLBACK
3405 gl.debugMessageCallback(debug_proc, &m_context);
3406 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
3407 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
3408
3409 GLint max_buffers = 0;
3410 GLfloat sum[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
3411
3412 /* Get max */
3413 gl.getIntegerv(GL_MAX_COMPUTE_UNIFORM_BLOCKS, &max_buffers);
3414 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3415
3416 /* UBO */
3417 /* Storage */
3418 std::vector<Buffer> uni_buffer;
3419 std::vector<GLuint> uni_buffer_ids;
3420
3421 uni_buffer.resize(max_buffers);
3422 uni_buffer_ids.resize(max_buffers);
3423
3424 /* Prepare buffers */
3425 for (GLint i = 0; i < max_buffers; ++i)
3426 {
3427 const GLfloat data[4] = {
3428 (GLfloat)(i * 4 + 0), (GLfloat)(i * 4 + 1), (GLfloat)(i * 4 + 2), (GLfloat)(i * 4 + 3),
3429 };
3430
3431 sum[0] += data[0];
3432 sum[1] += data[1];
3433 sum[2] += data[2];
3434 sum[3] += data[3];
3435
3436 uni_buffer[i].InitData(m_context, GL_UNIFORM_BUFFER, GL_DYNAMIC_COPY, buffer_size, data);
3437
3438 uni_buffer_ids[i] = uni_buffer[i].m_id;
3439 }
3440
3441 gl.bindBuffersBase(GL_UNIFORM_BUFFER, 0 /* first */, max_buffers /* count */, &uni_buffer_ids[0]);
3442 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersBase");
3443
3444 /* SSBO */
3445 Buffer ssb_buffer;
3446 ssb_buffer.InitData(m_context, GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, buffer_size, 0 /* data */);
3447
3448 ssb_buffer.BindBase(0);
3449
3450 /* Prepare program */
3451 size_t ubo_position = 0;
3452 size_t sum_position = 0;
3453 std::string cs_source = cs;
3454 for (GLint i = 0; i < max_buffers; ++i)
3455 {
3456 size_t ubo_start_position = ubo_position;
3457 size_t sum_start_position = sum_position;
3458
3459 GLchar index[16];
3460
3461 sprintf(index, "%d", i);
3462
3463 /* Add entry to ubo list */
3464 replaceToken("UBO_LIST", ubo_position, "UBO\nUBO_LIST", cs_source);
3465 ubo_position = ubo_start_position;
3466
3467 replaceToken("UBO", ubo_position, ubo, cs_source);
3468 ubo_position = ubo_start_position;
3469
3470 replaceToken("XXX", ubo_position, index, cs_source);
3471 replaceToken("XXX", ubo_position, index, cs_source);
3472 replaceToken("XXX", ubo_position, index, cs_source);
3473
3474 /* Add entry to sum list */
3475 replaceToken("SUM_LIST", sum_position, "bXXX.data + SUM_LIST", cs_source);
3476 sum_position = sum_start_position;
3477
3478 replaceToken("XXX", sum_position, index, cs_source);
3479 }
3480
3481 /* Remove token for lists */
3482 replaceToken(" + SUM_LIST", sum_position, "", cs_source);
3483 replaceToken("UBO_LIST", ubo_position, "", cs_source);
3484
3485 Program program(m_context);
3486 program.Init(cs_source.c_str(), "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
3487
3488 program.Use();
3489
3490 gl.dispatchCompute(1, 1, 1);
3491 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
3492
3493 gl.memoryBarrier(GL_ALL_BARRIER_BITS);
3494 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3495
3496 GLfloat* result = (GLfloat*)gl.mapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY);
3497 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
3498
3499 if (0 != memcmp(result, sum, 4 * sizeof(GLfloat)))
3500 {
3501 test_result = false;
3502 }
3503
3504 gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
3505 gl.getError(); /* Ignore error */
3506
3507 /* Set result */
3508 if (true == test_result)
3509 {
3510 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3511 }
3512 else
3513 {
3514 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3515 }
3516
3517 /* Done */
3518 return tcu::TestNode::STOP;
3519 }
3520
3521 /** Constructor
3522 *
3523 * @param context Test context
3524 **/
DispatchBindBuffersRangeTest(deqp::Context & context)3525 DispatchBindBuffersRangeTest::DispatchBindBuffersRangeTest(deqp::Context& context)
3526 : TestCase(context, "dispatch_bind_buffers_range", "Tests BindBuffersRange with dispatch command")
3527 {
3528 /* Nothing to be done */
3529 }
3530
3531 /** Execute test
3532 *
3533 * @return tcu::TestNode::STOP
3534 **/
iterate()3535 tcu::TestNode::IterateResult DispatchBindBuffersRangeTest::iterate()
3536 {
3537 static const GLchar* cs = "#version 440 core\n"
3538 "\n"
3539 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
3540 "\n"
3541 "layout (std140, binding = 0) uniform B0 { int data; } b0;"
3542 "layout (std140, binding = 1) uniform B1 { int data; } b1;"
3543 "layout (std140, binding = 2) uniform B2 { int data; } b2;"
3544 "layout (std140, binding = 3) uniform B3 { int data; } b3;"
3545 "\n"
3546 "layout (std140, binding = 0) buffer SSB {\n"
3547 " int sum;\n"
3548 "} ssb;\n"
3549 "\n"
3550 "void main()\n"
3551 "{\n"
3552 " //ssb.sum = b1.data;// + b1.data + b2.data + b3.data;\n"
3553 " ssb.sum = b0.data + b1.data + b2.data + b3.data;\n"
3554 "}\n"
3555 "\n";
3556
3557 static const GLint data[] = { 0x00010001, 0x01000100 };
3558 static const size_t n_buffers = 4;
3559 static const GLint sum = 0x02020202;
3560
3561 const Functions& gl = m_context.getRenderContext().getFunctions();
3562
3563 bool test_result = true;
3564
3565 #if DEBUG_ENBALE_MESSAGE_CALLBACK
3566 gl.debugMessageCallback(debug_proc, &m_context);
3567 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
3568 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
3569
3570 /* UBO */
3571 GLint offset_alignment = 0;
3572
3573 gl.getIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &offset_alignment);
3574 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3575
3576 /* Storage */
3577 Buffer uni_buffer;
3578 GLuint uni_buffer_ids[n_buffers];
3579 std::vector<GLubyte> uni_data;
3580 GLintptr uni_offsets[n_buffers];
3581 GLintptr uni_sizes[n_buffers];
3582
3583 const size_t buffer_size = (n_buffers - 1) * offset_alignment + sizeof(GLint);
3584 uni_data.resize(buffer_size);
3585
3586 for (size_t i = 0; i < buffer_size; ++i)
3587 {
3588 uni_data[i] = 0xaa;
3589 }
3590
3591 for (size_t i = 0; i < n_buffers; ++i)
3592 {
3593 void* dst = &uni_data[i * offset_alignment];
3594 const void* src = &data[(i % 2)];
3595
3596 memcpy(dst, src, sizeof(GLint));
3597 }
3598
3599 uni_buffer.InitData(m_context, GL_UNIFORM_BUFFER, GL_DYNAMIC_COPY, buffer_size, &uni_data[0]);
3600
3601 for (size_t i = 0; i < n_buffers; ++i)
3602 {
3603 uni_buffer_ids[i] = uni_buffer.m_id;
3604 uni_offsets[i] = i * offset_alignment;
3605 uni_sizes[i] = sizeof(GLint);
3606 }
3607
3608 gl.bindBuffersRange(GL_UNIFORM_BUFFER, 0 /* first */, n_buffers /* count */, &uni_buffer_ids[0], &uni_offsets[0],
3609 &uni_sizes[0]);
3610 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffersRange");
3611
3612 /* SSBO */
3613 Buffer ssb_buffer;
3614 ssb_buffer.InitData(m_context, GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, sizeof(GLint), 0 /* data */);
3615
3616 ssb_buffer.BindBase(0);
3617
3618 /* Prepare program */
3619 Program program(m_context);
3620 program.Init(cs, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
3621
3622 program.Use();
3623
3624 gl.dispatchCompute(1, 1, 1);
3625 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
3626
3627 gl.memoryBarrier(GL_ALL_BARRIER_BITS);
3628 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3629
3630 GLint* result = (GLint*)gl.mapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY);
3631 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
3632
3633 if (0 != memcmp(result, &sum, sizeof(sum)))
3634 {
3635 test_result = false;
3636 }
3637
3638 gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
3639 gl.getError(); /* Ignore error */
3640
3641 /* Set result */
3642 if (true == test_result)
3643 {
3644 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3645 }
3646 else
3647 {
3648 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3649 }
3650
3651 /* Done */
3652 return tcu::TestNode::STOP;
3653 }
3654
3655 /** Constructor
3656 *
3657 * @param context Test context
3658 **/
DispatchBindTexturesTest(deqp::Context & context)3659 DispatchBindTexturesTest::DispatchBindTexturesTest(deqp::Context& context)
3660 : TestCase(context, "dispatch_bind_textures", "Tests BindTextures with dispatch command")
3661 {
3662 /* Nothing to be done */
3663 }
3664
3665 /** Execute test
3666 *
3667 * @return tcu::TestNode::STOP
3668 **/
iterate()3669 tcu::TestNode::IterateResult DispatchBindTexturesTest::iterate()
3670 {
3671 static const GLchar* cs = "#version 440 core\n"
3672 "\n"
3673 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
3674 "\n"
3675 "SAMPLER_LIST\n"
3676 "layout (std140, binding = 0) buffer SSB {\n"
3677 " uint sum;\n"
3678 "} ssb;\n"
3679 "\n"
3680 "void main()\n"
3681 "{\n"
3682 " uvec4 sum = SUM_LIST;\n"
3683 " ssb.sum = sum.r\n;"
3684 "}\n"
3685 "\n";
3686
3687 static const GLchar* sampler = "layout (location = XXX) uniform SAMPLER sXXX;";
3688
3689 static const GLchar* sampling[] = {
3690 "texture(sXXX, COORDS)", "texture(sXXX, COORDS)", "texture(sXXX, COORDS)", "texture(sXXX, COORDS)",
3691 "texture(sXXX, COORDS)", "texelFetch(sXXX, COORDS)", "texture(sXXX, COORDS)", "texture(sXXX, COORDS)",
3692 "texture(sXXX, COORDS)", "texelFetch(sXXX, COORDS, 0)", "texelFetch(sXXX, COORDS, 0)"
3693 };
3694
3695 static const GLchar* samplers[] = { "usampler1D", "usampler1DArray", "usampler2D", "usampler2DArray",
3696 "usampler3D", "usamplerBuffer", "usamplerCube", "usamplerCubeArray",
3697 "usampler2DRect", "usampler2DMS", "usampler2DMSArray" };
3698
3699 static const GLchar* coordinates[] = {
3700 "0.5f",
3701 "vec2(0.5f, 0.0f)",
3702 "vec2(0.5f, 0.5f)",
3703 "vec3(0.5f, 0.5f, 0.0f)",
3704 "vec3(0.5f, 0.5f, 0.5f)",
3705 "0",
3706 "vec3(0.5f, 0.5f, 0.5f)",
3707 "vec4(0.5f, 0.5f, 0.5f, 0.0f)",
3708 "vec2(0.5f, 0.5f)",
3709 "ivec2(0, 0)",
3710 "ivec3(0, 0, 0)",
3711 };
3712
3713 static const GLuint depth = 6;
3714 static const GLuint height = 6;
3715 static const GLuint width = 6;
3716
3717 const Functions& gl = m_context.getRenderContext().getFunctions();
3718
3719 bool test_result = true;
3720
3721 #if DEBUG_ENBALE_MESSAGE_CALLBACK
3722 gl.debugMessageCallback(debug_proc, &m_context);
3723 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
3724 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
3725
3726 GLint max_textures = 0;
3727 GLint max_image_samples = 0;
3728 GLuint sum = 0;
3729
3730 /* Get max */
3731 gl.getIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &max_textures);
3732 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3733
3734 /* Check if load/store from multisampled images is supported */
3735 gl.getIntegerv(GL_MAX_IMAGE_SAMPLES, &max_image_samples);
3736 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3737
3738 /* Textures */
3739 /* Storage */
3740 std::vector<Texture> texture;
3741 std::vector<GLuint> texture_ids;
3742 Buffer texture_buffer;
3743
3744 texture.resize(max_textures);
3745 texture_ids.resize(max_textures);
3746
3747 /* Prepare */
3748 for (GLint i = 0; i < max_textures; ++i)
3749 {
3750 GLenum target = getTarget(i);
3751 if (target >= GL_TEXTURE_2D_MULTISAMPLE && max_image_samples == 0)
3752 target = GL_TEXTURE_2D;
3753
3754 GLuint data[width * height * depth];
3755
3756 for (GLuint j = 0; j < width * height * depth; ++j)
3757 {
3758 data[j] = i;
3759 }
3760
3761 sum += i;
3762
3763 bool is_array = false;
3764
3765 switch (target)
3766 {
3767 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
3768 is_array = true;
3769 /* Intentional fallthrough */
3770
3771 case GL_TEXTURE_2D_MULTISAMPLE:
3772 texture[i].InitStorage(m_context, target, 1, GL_R32UI, width, height, depth);
3773 fillMSTexture(m_context, texture[i].m_id, i, is_array);
3774 break;
3775
3776 case GL_TEXTURE_BUFFER:
3777 texture_buffer.InitData(m_context, GL_TEXTURE_BUFFER, GL_DYNAMIC_COPY, sizeof(data), data);
3778 texture[i].InitBuffer(m_context, GL_R32UI, texture_buffer.m_id);
3779 break;
3780
3781 default:
3782 texture[i].InitStorage(m_context, target, 1, GL_R32UI, width, height, depth);
3783 Texture::Bind(gl, texture[i].m_id, target);
3784 Texture::SubImage(gl, target, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height, depth,
3785 GL_RED_INTEGER, GL_UNSIGNED_INT, &data);
3786 gl.texParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3787 gl.texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3788 break;
3789 }
3790
3791 /* Clean */
3792 Texture::Bind(gl, 0, target);
3793
3794 texture_ids[i] = texture[i].m_id;
3795 }
3796
3797 gl.bindTextures(0 /* first */, max_textures /* count */, &texture_ids[0]);
3798 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTextures");
3799
3800 /* SSBO */
3801 Buffer ssb_buffer;
3802 ssb_buffer.InitData(m_context, GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, sizeof(GLuint), 0 /* data */);
3803
3804 ssb_buffer.BindBase(0);
3805
3806 /* Prepare program */
3807 size_t sam_position = 0;
3808 size_t sum_position = 0;
3809 std::string cs_source = cs;
3810 GLint max_target_index = (GLint)(max_image_samples > 0 ? s_n_texture_tragets : s_n_texture_tragets - 2);
3811 for (GLint i = 0; i < max_textures; ++i)
3812 {
3813 size_t sam_start_position = sam_position;
3814 size_t sum_start_position = sum_position;
3815
3816 GLchar index[16];
3817
3818 sprintf(index, "%d", i);
3819
3820 const GLchar* coords = 0;
3821 const GLchar* sampler_type = 0;
3822 const GLchar* sampling_code = 0;
3823
3824 if (i < max_target_index)
3825 {
3826 coords = coordinates[i];
3827 sampler_type = samplers[i];
3828 sampling_code = sampling[i];
3829 }
3830 else
3831 {
3832 coords = coordinates[2]; /* vec2(0.5f, 0.5f) */
3833 sampler_type = samplers[2]; /* usampler2D */
3834 sampling_code = sampling[2]; /* texture(sXXX, COORDS) */
3835 }
3836
3837 /* Add entry to ubo list */
3838 replaceToken("SAMPLER_LIST", sam_position, "SAMPLER\nSAMPLER_LIST", cs_source);
3839 sam_position = sam_start_position;
3840
3841 replaceToken("SAMPLER", sam_position, sampler, cs_source);
3842 sam_position = sam_start_position;
3843
3844 replaceToken("XXX", sam_position, index, cs_source);
3845 replaceToken("SAMPLER", sam_position, sampler_type, cs_source);
3846 replaceToken("XXX", sam_position, index, cs_source);
3847
3848 /* Add entry to sum list */
3849 replaceToken("SUM_LIST", sum_position, "SAMPLING + SUM_LIST", cs_source);
3850 sum_position = sum_start_position;
3851
3852 replaceToken("SAMPLING", sum_position, sampling_code, cs_source);
3853 sum_position = sum_start_position;
3854
3855 replaceToken("XXX", sum_position, index, cs_source);
3856 replaceToken("COORDS", sum_position, coords, cs_source);
3857 }
3858
3859 /* Remove token for lists */
3860 replaceToken(" + SUM_LIST", sum_position, "", cs_source);
3861 replaceToken("SAMPLER_LIST", sam_position, "", cs_source);
3862
3863 Program program(m_context);
3864 program.Init(cs_source.c_str(), "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
3865
3866 program.Use();
3867
3868 /* Set samplers */
3869 for (GLint i = 0; i < max_textures; ++i)
3870 {
3871 gl.uniform1i(i, i);
3872 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
3873 }
3874
3875 gl.dispatchCompute(1, 1, 1);
3876 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
3877
3878 gl.memoryBarrier(GL_ALL_BARRIER_BITS);
3879 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3880
3881 GLuint* result = (GLuint*)gl.mapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY);
3882 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
3883
3884 if (0 != memcmp(result, &sum, sizeof(sum)))
3885 {
3886 test_result = false;
3887 }
3888
3889 gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
3890 gl.getError(); /* Ignore error */
3891
3892 /* Set result */
3893 if (true == test_result)
3894 {
3895 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3896 }
3897 else
3898 {
3899 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3900 }
3901
3902 /* Done */
3903 return tcu::TestNode::STOP;
3904 }
3905
3906 /** Constructor
3907 *
3908 * @param context Test context
3909 **/
DispatchBindImageTexturesTest(deqp::Context & context)3910 DispatchBindImageTexturesTest::DispatchBindImageTexturesTest(deqp::Context& context)
3911 : TestCase(context, "dispatch_bind_image_textures", "Tests BindImageTextures with dispatch command")
3912 {
3913 /* Nothing to be done */
3914 }
3915
3916 /** Execute test
3917 *
3918 * @return tcu::TestNode::STOP
3919 **/
iterate()3920 tcu::TestNode::IterateResult DispatchBindImageTexturesTest::iterate()
3921 {
3922 static const GLchar* cs = "#version 440 core\n"
3923 "\n"
3924 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
3925 "\n"
3926 "IMAGE_LIST\n"
3927 "layout (std140, binding = 0) buffer SSB {\n"
3928 " uint sum;\n"
3929 "} ssb;\n"
3930 "\n"
3931 "void main()\n"
3932 "{\n"
3933 " uvec4 sum = SUM_LIST;\n"
3934 " ssb.sum = sum.r\n;"
3935 "}\n"
3936 "\n";
3937
3938 static const GLchar* image = "layout (location = XXX, r32ui) readonly uniform IMAGE iXXX;";
3939
3940 static const GLchar* loading[] = {
3941 "imageLoad(iXXX, COORDS)", "imageLoad(iXXX, COORDS)", "imageLoad(iXXX, COORDS)", "imageLoad(iXXX, COORDS)",
3942 "imageLoad(iXXX, COORDS)", "imageLoad(iXXX, COORDS)", "imageLoad(iXXX, COORDS)", "imageLoad(iXXX, COORDS)",
3943 "imageLoad(iXXX, COORDS)", "imageLoad(iXXX, COORDS, 0)", "imageLoad(iXXX, COORDS, 0)"
3944 };
3945
3946 static const GLchar* images[] = { "uimage1D", "uimage1DArray", "uimage2D", "uimage2DArray",
3947 "uimage3D", "uimageBuffer", "uimageCube", "uimageCubeArray",
3948 "uimage2DRect", "uimage2DMS", "uimage2DMSArray" };
3949
3950 static const GLchar* coordinates[] = {
3951 "0",
3952 "ivec2(0, 0)",
3953 "ivec2(0, 0)",
3954 "ivec3(0, 0, 0)",
3955 "ivec3(0, 0, 0)",
3956 "0",
3957 "ivec3(0, 0, 0)",
3958 "ivec3(0, 0, 0)",
3959 "ivec2(0, 0)",
3960 "ivec2(0, 0)",
3961 "ivec3(0, 0, 0)",
3962 };
3963
3964 static const GLuint depth = 6;
3965 static const GLuint height = 6;
3966 static const GLuint width = 6;
3967
3968 const Functions& gl = m_context.getRenderContext().getFunctions();
3969
3970 bool test_result = true;
3971
3972 #if DEBUG_ENBALE_MESSAGE_CALLBACK
3973 gl.debugMessageCallback(debug_proc, &m_context);
3974 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
3975 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
3976
3977 GLint max_textures = 0;
3978 GLint max_image_samples = 0;
3979 GLuint sum = 0;
3980
3981 /* Get max */
3982 gl.getIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &max_textures);
3983 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3984
3985 /* Check if load/store from multisampled images is supported */
3986 gl.getIntegerv(GL_MAX_IMAGE_SAMPLES, &max_image_samples);
3987 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3988
3989 /* Textures */
3990 /* Storage */
3991 std::vector<Texture> texture;
3992 std::vector<GLuint> texture_ids;
3993 Buffer texture_buffer;
3994
3995 texture.resize(max_textures);
3996 texture_ids.resize(max_textures);
3997
3998 /* Prepare */
3999 for (GLint i = 0; i < max_textures; ++i)
4000 {
4001 GLenum target = getTarget(i);
4002 if (target >= GL_TEXTURE_2D_MULTISAMPLE && max_image_samples == 0)
4003 target = GL_TEXTURE_2D;
4004
4005 GLuint data[width * height * depth];
4006
4007 for (GLuint j = 0; j < width * height * depth; ++j)
4008 {
4009 data[j] = i;
4010 }
4011
4012 sum += i;
4013
4014 bool is_array = false;
4015
4016 switch (target)
4017 {
4018 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
4019 is_array = true;
4020 /* Intentional fallthrough */
4021
4022 case GL_TEXTURE_2D_MULTISAMPLE:
4023 texture[i].InitStorage(m_context, target, 1, GL_R32UI, width, height, depth);
4024 fillMSTexture(m_context, texture[i].m_id, i, is_array);
4025 break;
4026
4027 case GL_TEXTURE_BUFFER:
4028 texture_buffer.InitData(m_context, GL_TEXTURE_BUFFER, GL_DYNAMIC_COPY, sizeof(data), data);
4029 texture[i].InitBuffer(m_context, GL_R32UI, texture_buffer.m_id);
4030 break;
4031
4032 default:
4033 texture[i].InitStorage(m_context, target, 1, GL_R32UI, width, height, depth);
4034 Texture::Bind(gl, texture[i].m_id, target);
4035 Texture::SubImage(gl, target, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height, depth,
4036 GL_RED_INTEGER, GL_UNSIGNED_INT, &data);
4037 break;
4038 }
4039
4040 /* Clean */
4041 Texture::Bind(gl, 0, target);
4042
4043 texture_ids[i] = texture[i].m_id;
4044 }
4045
4046 gl.bindImageTextures(0 /* first */, max_textures /* count */, &texture_ids[0]);
4047 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTextures");
4048
4049 /* SSBO */
4050 Buffer ssb_buffer;
4051 ssb_buffer.InitData(m_context, GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, sizeof(GLuint), 0 /* data */);
4052
4053 ssb_buffer.BindBase(0);
4054
4055 /* Prepare program */
4056 size_t load_position = 0;
4057 size_t sum_position = 0;
4058 std::string cs_source = cs;
4059 GLint max_target_index = (GLint)(max_image_samples > 0 ? s_n_texture_tragets : s_n_texture_tragets - 2);
4060 for (GLint i = 0; i < max_textures; ++i)
4061 {
4062 size_t load_start_position = load_position;
4063 size_t sum_start_position = sum_position;
4064
4065 GLchar index[16];
4066
4067 sprintf(index, "%d", i);
4068
4069 const GLchar* coords = 0;
4070 const GLchar* image_type = 0;
4071 const GLchar* loading_code = 0;
4072
4073 if (i < max_target_index)
4074 {
4075 coords = coordinates[i];
4076 image_type = images[i];
4077 loading_code = loading[i];
4078 }
4079 else
4080 {
4081 coords = coordinates[2]; /* vec2(0.5f, 0.5f) */
4082 image_type = images[2]; /* usampler2D */
4083 loading_code = loading[2]; /* texture(sXXX, COORDS) */
4084 }
4085
4086 /* Add entry to ubo list */
4087 replaceToken("IMAGE_LIST", load_position, "IMAGE\nIMAGE_LIST", cs_source);
4088 load_position = load_start_position;
4089
4090 replaceToken("IMAGE", load_position, image, cs_source);
4091 load_position = load_start_position;
4092
4093 replaceToken("XXX", load_position, index, cs_source);
4094 replaceToken("IMAGE", load_position, image_type, cs_source);
4095 replaceToken("XXX", load_position, index, cs_source);
4096
4097 /* Add entry to sum list */
4098 replaceToken("SUM_LIST", sum_position, "LOADING + SUM_LIST", cs_source);
4099 sum_position = sum_start_position;
4100
4101 replaceToken("LOADING", sum_position, loading_code, cs_source);
4102 sum_position = sum_start_position;
4103
4104 replaceToken("XXX", sum_position, index, cs_source);
4105 replaceToken("COORDS", sum_position, coords, cs_source);
4106 }
4107
4108 /* Remove token for lists */
4109 replaceToken(" + SUM_LIST", sum_position, "", cs_source);
4110 replaceToken("IMAGE_LIST", load_position, "", cs_source);
4111
4112 Program program(m_context);
4113 program.Init(cs_source.c_str(), "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
4114
4115 program.Use();
4116
4117 /* Set images */
4118 for (GLint i = 0; i < max_textures; ++i)
4119 {
4120 gl.uniform1i(i, i);
4121 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
4122 }
4123
4124 gl.dispatchCompute(1, 1, 1);
4125 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
4126
4127 gl.memoryBarrier(GL_ALL_BARRIER_BITS);
4128 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
4129
4130 GLuint* result = (GLuint*)gl.mapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY);
4131 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
4132
4133 if (0 != memcmp(result, &sum, sizeof(sum)))
4134 {
4135 test_result = false;
4136 }
4137
4138 gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
4139 gl.getError(); /* Ignore error */
4140
4141 /* Set result */
4142 if (true == test_result)
4143 {
4144 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
4145 }
4146 else
4147 {
4148 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4149 }
4150
4151 /* Done */
4152 return tcu::TestNode::STOP;
4153 }
4154
4155 /** Constructor
4156 *
4157 * @param context Test context
4158 **/
DispatchBindSamplersTest(deqp::Context & context)4159 DispatchBindSamplersTest::DispatchBindSamplersTest(deqp::Context& context)
4160 : TestCase(context, "dispatch_bind_samplers", "Tests BindSamplers with dispatch command")
4161 {
4162 /* Nothing to be done */
4163 }
4164
4165 /** Execute test
4166 *
4167 * @return tcu::TestNode::STOP
4168 **/
iterate()4169 tcu::TestNode::IterateResult DispatchBindSamplersTest::iterate()
4170 {
4171 static const GLchar* cs = "#version 440 core\n"
4172 "\n"
4173 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
4174 "\n"
4175 "SAMPLER_LIST\n"
4176 "layout (std140, binding = 0) buffer SSB {\n"
4177 " uint sum;\n"
4178 "} ssb;\n"
4179 "\n"
4180 "void main()\n"
4181 "{\n"
4182 " uvec4 sum = SUM_LIST;\n"
4183 " ssb.sum = sum.r\n;"
4184 "}\n"
4185 "\n";
4186
4187 static const GLchar* sampler = "layout (location = XXX) uniform usampler2D sXXX;";
4188
4189 static const GLchar* sampling = "texture(sXXX, vec2(1.5f, 0.5f))";
4190
4191 static const GLuint depth = 1;
4192 static const GLuint height = 8;
4193 static const GLuint width = 8;
4194
4195 const Functions& gl = m_context.getRenderContext().getFunctions();
4196
4197 bool test_result = true;
4198
4199 #if DEBUG_ENBALE_MESSAGE_CALLBACK
4200 gl.debugMessageCallback(debug_proc, &m_context);
4201 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
4202 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
4203
4204 GLint max_textures = 0;
4205
4206 /* Get max */
4207 gl.getIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &max_textures);
4208 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
4209
4210 /* Textures */
4211 /* Storage */
4212 std::vector<GLuint> sampler_ids;
4213 std::vector<Texture> texture;
4214 std::vector<GLuint> texture_ids;
4215
4216 sampler_ids.resize(max_textures);
4217 texture.resize(max_textures);
4218 texture_ids.resize(max_textures);
4219
4220 GLuint data[width * height * depth];
4221
4222 for (GLuint j = 0; j < width * height; ++j)
4223 {
4224 data[j] = 0;
4225 }
4226
4227 {
4228 const size_t last_line_offset = (height - 1) * width;
4229 const size_t last_pixel_in_line_offset = width - 1;
4230
4231 for (GLuint j = 0; j < width; ++j)
4232 {
4233 data[j] = 1;
4234 data[j + last_line_offset] = 1;
4235 }
4236
4237 for (GLuint j = 0; j < height; ++j)
4238 {
4239 const size_t line_offset = j * width;
4240
4241 data[line_offset] = 1;
4242 data[line_offset + last_pixel_in_line_offset] = 1;
4243 }
4244 }
4245
4246 /* Prepare */
4247 for (GLint i = 0; i < max_textures; ++i)
4248 {
4249 texture[i].InitStorage(m_context, GL_TEXTURE_2D, 1, GL_R32UI, width, height, depth);
4250 Texture::Bind(gl, texture[i].m_id, GL_TEXTURE_2D);
4251 Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height, depth,
4252 GL_RED_INTEGER, GL_UNSIGNED_INT, &data);
4253
4254 texture_ids[i] = texture[i].m_id;
4255 }
4256
4257 /* Clean */
4258 Texture::Bind(gl, 0, GL_TEXTURE_2D);
4259
4260 /* Execute the test */
4261 gl.bindTextures(0 /* first */, max_textures /* count */, &texture_ids[0]);
4262 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTextures");
4263
4264 /* SSBO */
4265 Buffer ssb_buffer;
4266 ssb_buffer.InitData(m_context, GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, sizeof(GLuint), 0 /* data */);
4267
4268 ssb_buffer.BindBase(0);
4269
4270 /* Prepare program */
4271 size_t sam_position = 0;
4272 size_t sum_position = 0;
4273 std::string cs_source = cs;
4274
4275 for (GLint i = 0; i < max_textures; ++i)
4276 {
4277 size_t sam_start_position = sam_position;
4278 size_t sum_start_position = sum_position;
4279
4280 GLchar index[16];
4281
4282 sprintf(index, "%d", i);
4283
4284 /* Add entry to ubo list */
4285 replaceToken("SAMPLER_LIST", sam_position, "SAMPLER\nSAMPLER_LIST", cs_source);
4286 sam_position = sam_start_position;
4287
4288 replaceToken("SAMPLER", sam_position, sampler, cs_source);
4289 sam_position = sam_start_position;
4290
4291 replaceToken("XXX", sam_position, index, cs_source);
4292 replaceToken("XXX", sam_position, index, cs_source);
4293
4294 /* Add entry to sum list */
4295 replaceToken("SUM_LIST", sum_position, "SAMPLING + SUM_LIST", cs_source);
4296 sum_position = sum_start_position;
4297
4298 replaceToken("SAMPLING", sum_position, sampling, cs_source);
4299 sum_position = sum_start_position;
4300
4301 replaceToken("XXX", sum_position, index, cs_source);
4302 }
4303
4304 /* Remove token for lists */
4305 replaceToken(" + SUM_LIST", sum_position, "", cs_source);
4306 replaceToken("SAMPLER_LIST", sam_position, "", cs_source);
4307
4308 Program program(m_context);
4309 program.Init(cs_source.c_str(), "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
4310
4311 program.Use();
4312
4313 /* Set texture units */
4314 for (GLint i = 0; i < max_textures; ++i)
4315 {
4316 gl.uniform1i(i, i);
4317 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
4318 }
4319
4320 /* Prepare samplers */
4321 gl.genSamplers(max_textures, &sampler_ids[0]);
4322 GLU_EXPECT_NO_ERROR(gl.getError(), "GenSamplers");
4323
4324 try
4325 {
4326 gl.bindSamplers(0 /* first */, max_textures /* count */, &sampler_ids[0]);
4327 GLU_EXPECT_NO_ERROR(gl.getError(), "BindSamplers");
4328
4329 for (GLint i = 0; i < max_textures; ++i)
4330 {
4331 gl.samplerParameteri(sampler_ids[i], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
4332 gl.samplerParameteri(sampler_ids[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4333 gl.samplerParameteri(sampler_ids[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4334 GLU_EXPECT_NO_ERROR(gl.getError(), "SamplerParameteri");
4335 }
4336
4337 gl.dispatchCompute(1, 1, 1);
4338 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
4339
4340 gl.memoryBarrier(GL_ALL_BARRIER_BITS);
4341 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
4342 }
4343 catch (const std::exception&)
4344 {
4345 gl.deleteSamplers(max_textures, &sampler_ids[0]);
4346
4347 TCU_FAIL("Unexpected error generated");
4348 }
4349
4350 /* Remove samplers */
4351 gl.deleteSamplers(max_textures, &sampler_ids[0]);
4352
4353 /* Verify results */
4354 GLuint* result = (GLuint*)gl.mapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY);
4355 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
4356
4357 if (0 != memcmp(result, &max_textures, sizeof(max_textures)))
4358 {
4359 test_result = false;
4360 }
4361
4362 gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
4363 gl.getError(); /* Ignore error */
4364
4365 /* Set result */
4366 if (true == test_result)
4367 {
4368 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
4369 }
4370 else
4371 {
4372 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4373 }
4374
4375 /* Done */
4376 return tcu::TestNode::STOP;
4377 }
4378
4379 /** Constructor
4380 *
4381 * @param context Test context
4382 **/
DrawBindVertexBuffersTest(deqp::Context & context)4383 DrawBindVertexBuffersTest::DrawBindVertexBuffersTest(deqp::Context& context)
4384 : TestCase(context, "draw_bind_vertex_buffers", "Tests BindVertexBuffers command with drawArrays")
4385 {
4386 /* Nothing to be done */
4387 }
4388
4389 /** Execute test
4390 *
4391 * @return tcu::TestNode::STOP
4392 **/
iterate()4393 tcu::TestNode::IterateResult DrawBindVertexBuffersTest::iterate()
4394 {
4395 static const GLchar* vs = "#version 440 core\n"
4396 "\n"
4397 "ATTRIBUTE_LIST\n"
4398 "\n"
4399 "out vec4 vs_gs_sum;\n"
4400 "\n"
4401 "void main()\n"
4402 "{\n"
4403 " vs_gs_sum = SUM_LIST;\n"
4404 "}\n"
4405 "\n";
4406
4407 static const GLchar* gs = "#version 440 core\n"
4408 "\n"
4409 "layout(points) in;\n"
4410 "layout(triangle_strip, max_vertices = 4) out;\n"
4411 "\n"
4412 "in vec4 vs_gs_sum[];\n"
4413 "out vec4 gs_fs_sum;\n"
4414 "\n"
4415 "void main()\n"
4416 "{\n"
4417 " gs_fs_sum = vs_gs_sum[0];\n"
4418 " gl_Position = vec4(-1, -1, 0, 1);\n"
4419 " EmitVertex();\n"
4420 " gs_fs_sum = vs_gs_sum[0];\n"
4421 " gl_Position = vec4(-1, 1, 0, 1);\n"
4422 " EmitVertex();\n"
4423 " gs_fs_sum = vs_gs_sum[0];\n"
4424 " gl_Position = vec4(1, -1, 0, 1);\n"
4425 " EmitVertex();\n"
4426 " gs_fs_sum = vs_gs_sum[0];\n"
4427 " gl_Position = vec4(1, 1, 0, 1);\n"
4428 " EmitVertex();\n"
4429 "}\n"
4430 "\n";
4431
4432 static const GLchar* fs = "#version 440 core\n"
4433 "\n"
4434 "in vec4 gs_fs_sum;\n"
4435 "out vec4 fs_out;\n"
4436 "\n"
4437 "void main()\n"
4438 "{\n"
4439 " fs_out = gs_fs_sum;\n"
4440 "}\n"
4441 "\n";
4442
4443 static const GLchar* attribute = "layout (location = XXX) in vec4 aXXX;";
4444
4445 static const GLuint height = 8;
4446 static const GLuint width = 8;
4447
4448 const Functions& gl = m_context.getRenderContext().getFunctions();
4449
4450 bool test_result = true;
4451
4452 #if DEBUG_ENBALE_MESSAGE_CALLBACK
4453 gl.debugMessageCallback(debug_proc, &m_context);
4454 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
4455 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
4456
4457 static const GLintptr attribute_size = 4 * sizeof(GLfloat);
4458
4459 GLint max_buffers = 0;
4460 GLuint vao = 0;
4461
4462 /* Get max */
4463 gl.getIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &max_buffers);
4464 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
4465
4466 /* Storage */
4467 Buffer buffer;
4468 std::vector<GLuint> buffer_ids;
4469 std::vector<GLfloat> data;
4470 std::vector<GLintptr> offsets;
4471 std::vector<GLsizei> strides;
4472
4473 buffer_ids.resize(max_buffers);
4474 data.resize(max_buffers * 4);
4475 offsets.resize(max_buffers);
4476 strides.resize(max_buffers);
4477
4478 /* Prepare data */
4479 const GLfloat value = 1.0f / (GLfloat)max_buffers;
4480
4481 for (GLint i = 0; i < max_buffers; ++i)
4482 {
4483 data[i * 4 + 0] = value;
4484 data[i * 4 + 1] = value;
4485 data[i * 4 + 2] = value;
4486 data[i * 4 + 3] = value;
4487 }
4488
4489 /* Prepare buffer */
4490 buffer.InitData(m_context, GL_ARRAY_BUFFER, GL_DYNAMIC_COPY, data.size() * sizeof(GLfloat), &data[0]);
4491
4492 for (GLint i = 0; i < max_buffers; ++i)
4493 {
4494 buffer_ids[i] = buffer.m_id;
4495 offsets[i] = i * attribute_size;
4496 strides[i] = attribute_size;
4497 }
4498
4499 /* Prepare FBO */
4500 Framebuffer framebuffer(m_context);
4501 Texture texture;
4502
4503 texture.InitStorage(m_context, GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, width, height, 1 /* depth */);
4504
4505 /* */
4506 Framebuffer::Generate(gl, framebuffer.m_id);
4507 Framebuffer::Bind(gl, GL_DRAW_FRAMEBUFFER, framebuffer.m_id);
4508 Framebuffer::AttachTexture(gl, GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.m_id, 0 /* level */, width,
4509 height);
4510
4511 /* Prepare program */
4512 size_t attr_position = 0;
4513 size_t sum_position = 0;
4514 std::string vs_source = vs;
4515 for (GLint i = 0; i < max_buffers; ++i)
4516 {
4517 size_t attr_start_position = attr_position;
4518 size_t sum_start_position = sum_position;
4519
4520 GLchar index[16];
4521
4522 sprintf(index, "%d", i);
4523
4524 /* Add entry to ubo list */
4525 replaceToken("ATTRIBUTE_LIST", attr_position, "ATTRIBUTE\nATTRIBUTE_LIST", vs_source);
4526 attr_position = attr_start_position;
4527
4528 replaceToken("ATTRIBUTE", attr_position, attribute, vs_source);
4529 attr_position = attr_start_position;
4530
4531 replaceToken("XXX", attr_position, index, vs_source);
4532 replaceToken("XXX", attr_position, index, vs_source);
4533
4534 /* Add entry to sum list */
4535 replaceToken("SUM_LIST", sum_position, "aXXX + SUM_LIST", vs_source);
4536 sum_position = sum_start_position;
4537
4538 replaceToken("XXX", sum_position, index, vs_source);
4539 }
4540
4541 /* Remove token for lists */
4542 replaceToken(" + SUM_LIST", sum_position, "", vs_source);
4543 replaceToken("ATTRIBUTE_LIST", attr_position, "", vs_source);
4544
4545 Program program(m_context);
4546 program.Init("" /* cs */, fs, gs, "" /* tcs */, "" /* tes */, vs_source.c_str());
4547
4548 program.Use();
4549
4550 gl.genVertexArrays(1, &vao);
4551 GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
4552
4553 try
4554 {
4555 gl.bindVertexArray(vao);
4556 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArrays");
4557
4558 for (GLint i = 0; i < max_buffers; ++i)
4559 {
4560 gl.enableVertexAttribArray(i);
4561 GLU_EXPECT_NO_ERROR(gl.getError(), "EnableVertexAttribArray");
4562 }
4563
4564 /* */
4565 gl.bindVertexBuffers(0, max_buffers, &buffer_ids[0], &offsets[0], &strides[0]);
4566 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexBuffers");
4567
4568 /* */
4569 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
4570 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
4571
4572 for (GLint i = 0; i < max_buffers; ++i)
4573 {
4574 gl.disableVertexAttribArray(i);
4575 GLU_EXPECT_NO_ERROR(gl.getError(), "DisableVertexAttribArray");
4576 }
4577 }
4578 catch (const std::exception&)
4579 {
4580 gl.deleteVertexArrays(1, &vao);
4581
4582 TCU_FAIL("Unexpected error generated");
4583 }
4584
4585 gl.deleteVertexArrays(1, &vao);
4586 GLU_EXPECT_NO_ERROR(gl.getError(), "DeleteVertexArrays");
4587
4588 /* Verify results */
4589 GLuint pixels[width * height];
4590 for (GLuint i = 0; i < width * height; ++i)
4591 {
4592 pixels[i] = 0;
4593 }
4594
4595 Texture::Bind(gl, texture.m_id, GL_TEXTURE_2D);
4596
4597 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
4598
4599 /* Unbind */
4600 Texture::Bind(gl, 0, GL_TEXTURE_2D);
4601
4602 /* Verify */
4603 for (GLuint i = 0; i < width * height; ++i)
4604 {
4605 if (0xffffffff != pixels[i])
4606 {
4607 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << (GLuint)pixels[i]
4608 << " at offset: " << i << tcu::TestLog::EndMessage;
4609
4610 test_result = false;
4611
4612 break;
4613 }
4614 }
4615
4616 /* Set result */
4617 if (true == test_result)
4618 {
4619 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
4620 }
4621 else
4622 {
4623 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4624 }
4625
4626 /* Done */
4627 return tcu::TestNode::STOP;
4628 }
4629 } /* MultiBind */
4630
4631 /** Constructor.
4632 *
4633 * @param context Rendering context.
4634 **/
MultiBindTests(deqp::Context & context)4635 MultiBindTests::MultiBindTests(deqp::Context& context)
4636 : TestCaseGroup(context, "multi_bind", "Verifies \"multi bind\" functionality")
4637 {
4638 /* Left blank on purpose */
4639 }
4640
4641 /** Initializes a multi_bind test group.
4642 *
4643 **/
init(void)4644 void MultiBindTests::init(void)
4645 {
4646 addChild(new MultiBind::DispatchBindTexturesTest(m_context));
4647
4648 addChild(new MultiBind::ErrorsBindBuffersTest(m_context));
4649 addChild(new MultiBind::ErrorsBindTexturesTest(m_context));
4650 addChild(new MultiBind::ErrorsBindSamplersTest(m_context));
4651 addChild(new MultiBind::ErrorsBindImageTexturesTest(m_context));
4652 addChild(new MultiBind::ErrorsBindVertexBuffersTest(m_context));
4653 addChild(new MultiBind::FunctionalBindBuffersBaseTest(m_context));
4654 addChild(new MultiBind::FunctionalBindBuffersRangeTest(m_context));
4655 addChild(new MultiBind::FunctionalBindTexturesTest(m_context));
4656 addChild(new MultiBind::FunctionalBindSamplersTest(m_context));
4657 addChild(new MultiBind::FunctionalBindImageTexturesTest(m_context));
4658 addChild(new MultiBind::FunctionalBindVertexBuffersTest(m_context));
4659 addChild(new MultiBind::DispatchBindBuffersBaseTest(m_context));
4660 addChild(new MultiBind::DispatchBindBuffersRangeTest(m_context));
4661
4662 addChild(new MultiBind::DispatchBindImageTexturesTest(m_context));
4663 addChild(new MultiBind::DispatchBindSamplersTest(m_context));
4664 addChild(new MultiBind::DrawBindVertexBuffersTest(m_context));
4665 }
4666
4667 } /* gl4cts namespace */
4668